# encoding: ascii
# api: powershell
# title: Suspend-Process
# description: A couple of functions to suspend and resume applications (like what you do with Resource Monitor).
# version: 0.1
# type: function
# author: Joel Bennett
# license: CC0
# function: Suspend-Process
# x-poshcode-id: 2995
# x-archived: 2017-02-26T12:48:33
# x-published: 2012-10-09T11:37:00
#
# Get-Process notepad | Suspend-Process
# Get-Process notepad | Resume-Process
# h3. I can’t emphasize enough that this is a dangerous tool.
# Using Suspend-Process in particular may crash applications, work wonderfully, cause bluescreens, corrupt memory, or start a thermonuclear war. Please use responsibly.
#
Add-Type -Name Threader -Namespace "" -Member @"
[Flags]
public enum ThreadAccess : int
{
Terminate = (0x0001),
SuspendResume = (0x0002),
GetContext = (0x0008),
SetContext = (0x0010),
SetInformation = (0x0020),
GetInformation = (0x0040),
SetThreadToken = (0x0080),
Impersonate = (0x0100),
DirectImpersonation = (0x0200)
}
[Flags]
public enum ProcessAccess : uint
{
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
SuspendResume = 0x00000800,
Synchronize = 0x00100000,
All = 0x001F0FFF
}
[DllImport("ntdll.dll", EntryPoint = "NtSuspendProcess", SetLastError = true)]
public static extern uint SuspendProcess(IntPtr processHandle);
[DllImport("ntdll.dll", EntryPoint = "NtResumeProcess", SetLastError = true)]
public static extern uint ResumeProcess(IntPtr processHandle);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
public static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
public static extern int ResumeThread(IntPtr hThread);
"@
function Suspend-Process {
param(
[Parameter(ValueFromPipeline=$true,Mandatory=$true)]
[System.Diagnostics.Process]
$Process
)
process {
if(($pProc = [Threader]::OpenProcess("SuspendResume", $false, $Process.Id)) -ne [IntPtr]::Zero) {
Write-Verbose "Suspending Process: $pProc"
$result = [Threader]::SuspendProcess($pProc)
if($result -ne 0) {
Write-Error "Failed to Suspend: $result"
## TODO: GetLastError()
}
[Threader]::CloseHandle($pProc)
} else {
Write-Error "Unable to open Process $($Process.Id), are you running elevated?"
## TODO: Check if they're elevated and otherwise GetLastError()
}
}
}
function Resume-Process {
param(
[Parameter(ValueFromPipeline=$true,Mandatory=$true)]
[System.Diagnostics.Process]
$Process
)
process {
if(($pProc = [Threader]::OpenProcess("SuspendResume", $false, $Process.Id)) -ne [IntPtr]::Zero) {
Write-Verbose "Resuming Process: $pProc"
$result = [Threader]::ResumeProcess($pProc)
if($result -ne 0) {
Write-Error "Failed to Suspend: $result"
## TODO: GetLastError()
}
[Threader]::CloseHandle($pProc)
} else {
Write-Error "Unable to open Process $($Process.Id), are you running elevated?"
## TODO: Check if they're elevated and otherwise GetLastError()
}
}
}
function Suspend-Thread {
param(
[Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)]
[System.Diagnostics.ProcessThread[]]
[Alias("Threads")]
$Thread
)
process {
if(($pThread = [Threader]::OpenThread("SuspendResume", $false, $Thread.Id)) -ne [IntPtr]::Zero) {
Write-Verbose "Suspending Thread: $pThread"
[Threader]::SuspendThread($pThread)
[Threader]::CloseHandle($pThread)
} else {
Write-Error "Unable to open Thread $($Thread.Id), are you running elevated?"
## TODO: Check if they're elevated and otherwise GetLastError()
}
}
}
function Resume-Thread {
param(
[Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)]
[System.Diagnostics.ProcessThread[]]
[Alias("Threads")]
$Thread
)
process {
if(($pThread = [Threader]::OpenThread("SuspendResume", $false, $Thread.Id)) -ne [IntPtr]::Zero) {
Write-Verbose "Resuming Thread: $pThread"
[Threader]::ResumeThread($pThread)
[Threader]::CloseHandle($pThread)
} else {
Write-Error "Unable to open Thread $($Thread.Id), are you running elevated?"
## TODO: Check if they're elevated and otherwise GetLastError()
}
}
}