Skip to content

Instantly share code, notes, and snippets.

@stakach
Last active September 4, 2024 01:09
Show Gist options
  • Save stakach/396a623cc102679136af29ded5a4d004 to your computer and use it in GitHub Desktop.
Save stakach/396a623cc102679136af29ded5a4d004 to your computer and use it in GitHub Desktop.
powershell code for cleaning up all processes and child processes launched as part of the script
if (-not [System.Management.Automation.PSTypeName]'JobObject'.Type) {
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class JobObject
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool TerminateJobObject(IntPtr hJob, uint uExitCode);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
}
"@
}
# Create a Job Object
$jobHandle = [JobObject]::CreateJobObject([IntPtr]::Zero, "TestJobObject")
if ($jobHandle -eq [IntPtr]::Zero) {
throw "Failed to create Job Object: $([System.ComponentModel.Win32Exception]::new([Runtime.InteropServices.Marshal]::GetLastWin32Error()).Message)"
}
try {
# Start the child process (launch some processes from this, i.e. msinfo32 etc and then ctrl-c this script)
$childProcess = Start-Process -FilePath "cmd.exe" -PassThru
# Assign the process to the job object
$processHandle = (Get-Process -Id $childProcess.Id).Handle
if (-not [JobObject]::AssignProcessToJobObject($jobHandle, $processHandle)) {
throw "Failed to assign process to Job Object: $([System.ComponentModel.Win32Exception]::new([Runtime.InteropServices.Marshal]::GetLastWin32Error()).Message)"
}
# Wait for either Ctrl-C or the process to exit
while (!$childProcess.HasExited) {
Start-Sleep -Milliseconds 500
}
} finally {
# Clean up - explicitly terminate all processes in the job
Write-Host "Terminating job object and exiting."
if (-not [JobObject]::TerminateJobObject($jobHandle, 0)) {
Write-Host "Failed to terminate Job Object: $([System.ComponentModel.Win32Exception]::new([Runtime.InteropServices.Marshal]::GetLastWin32Error()).Message)"
}
if (-not [JobObject]::CloseHandle($jobHandle)) {
Write-Host "Failed to close Job Object handle: $([System.ComponentModel.Win32Exception]::new([Runtime.InteropServices.Marshal]::GetLastWin32Error()).Message)"
}
exit 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment