Kill child processes when the parent powershell process is killed

My usage example:

In visual studio, when debugging, I run powershell and cram script, which, along with several actions, launches the project executable file as follows:

&$exeToStart $exeParams | Out-Host

This works well when I run the script from the powershell console. My problems start when I stop debugging using the VS stop icon, which essentially kills the powershell process that runs this script, thereby leaving a freezing exe process that I have to manually kill afterwards.

So my question is how to make sure that when the visual studio kills the parent powershell process, the child process also kills with it?

+4
source share
3 answers

I doubt that Visual Studio has a way to terminate all child processes when you stop debugging.

One solution would be to run a PowerShell script to clean up. You can use the ParentProcessId property in Win32_Process CimInstance. It might look something like this (using PowerShell V3):

 Get-CimInstance win32_process |
    ? { (Get-Process -id $_.ParentProcessId -ea Ignore) -eq $null } |
    Stop-Process -WhatIf

This will return a list of processes in which the parent process no longer exists. Please note that for effective use it is necessary to filter the processes that, as you know, you started. For example, if I tried to kill the whole process returned by the above command, I would try to kill csrss.exe, wininit.exe and other processes that I would not want to kill.

, Visual Studio, PowerShell script. PowerShell, . http://www.wintellect.com/blogs/jrobbins/using-nuget-powershell-to-replace-missing-macros-in-dev-11 , .

+2

-, "". . .

#TestJob.ps1
$CreateJobObjectSignature = @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public class ClsNativ
{
  public enum JOBOBJECTINFOCLASS
  {
    AssociateCompletionPortInformation = 7,
    BasicLimitInformation = 2,
    BasicUIRestrictions = 4,
    EndOfJobTimeInformation = 6,
    ExtendedLimitInformation = 9,
    SecurityLimitInformation = 5,
    GroupInformation = 11
  }

  [StructLayout(LayoutKind.Sequential)]
  struct JOBOBJECT_BASIC_LIMIT_INFORMATION
  {
    public Int64 PerProcessUserTimeLimit;
    public Int64 PerJobUserTimeLimit;
    public UInt32 LimitFlags;
    public UIntPtr MinimumWorkingSetSize;
    public UIntPtr MaximumWorkingSetSize;
    public UInt32 ActiveProcessLimit;
    public Int64 Affinity;
    public UInt32 PriorityClass;
    public UInt32 SchedulingClass;
  }


  [StructLayout(LayoutKind.Sequential)]
  struct IO_COUNTERS
  {
    public UInt64 ReadOperationCount;
    public UInt64 WriteOperationCount;
    public UInt64 OtherOperationCount;
    public UInt64 ReadTransferCount;
    public UInt64 WriteTransferCount;
    public UInt64 OtherTransferCount;
  }

  [StructLayout(LayoutKind.Sequential)]
  struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
  {
    public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
    public IO_COUNTERS IoInfo;
    public UIntPtr ProcessMemoryLimit;
    public UIntPtr JobMemoryLimit;
    public UIntPtr PeakProcessMemoryUsed;
    public UIntPtr PeakJobMemoryUsed;
  }

  [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
  public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string lpName);

  [DllImport("kernel32.dll")]
  public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);

  [DllImport("kernel32.dll")]
  public static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECTINFOCLASS JobObjectInfoClass, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

  [DllImport("kernel32.dll")]
  public static extern IntPtr GetCurrentProcess();


  private const UInt32 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;
  public ClsNativ()
  {
    IntPtr hJob = CreateJobObject(IntPtr.Zero, "JobName");

    JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
    info.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

    JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
    extendedInfo.BasicLimitInformation = info;

    int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
    IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
    Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

    SetInformationJobObject(hJob, JOBOBJECTINFOCLASS.ExtendedLimitInformation, extendedInfoPtr, (uint)length);

    IntPtr hProcess = GetCurrentProcess();
    bool blRc = AssignProcessToJobObject(hJob, hProcess);

    Marshal.FreeHGlobal(extendedInfoPtr);
  }
}
"@



Add-Type -TypeDefinition $CreateJobObjectSignature 
$a = New-Object ClsNativ

& notepad.exe
Start-Process -FilePath "c:\windows\system32\calc.exe"

Read-Host "Push return key !"

. , , PowerShell, "JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE", , , . PowerShell . , - PowerShell, , . .

Seven x64 PowerShell. , , ( VS 2010)

Windows 8 x64 PowerShell.

:

powershell -file "C:\temp\TestJob.ps1"

Windows Seven, Visual Studio normaly, , :

enter image description here

Visual Studio 2010 WMI, :

Invoke-WmiMethod -path win32_process -name create -argumentlist "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe"

:

enter image description here

, PowerShell , , PowerShell :

enter image description here

+1

Powershell script:

Get-CimInstance win32_process -Filter "Name like 'myprocess.exe'" | ? { (Get-Process -id $_.ParentProcessId -ea Ignore) -eq $null } | Select-Object ProcessId | ? { Stop-Process $_.ProcessId -Force }

This is a Powershell script that worked for me after reading Jason's answer.

0
source

All Articles