static ChildProcessTracker() {
// This feature requires Windows 8 or later. To support Windows 7 requires
// registry settings to be added if you are using Visual Studio plus an
// app.manifest change.
// http://stackoverflow.com/a/4232259/386091
// http://stackoverflow.com/a/9507862/386091
if (Environment.OSVersion.Version < new Version(6, 2)) return;
// The job name is optional (and can be null) but it helps with diagnostics.
// If it's not null, it has to be unique. Use SysInternals' Handle command-line
// utility: handle -a ChildProcessTracker
var jobName = "ChildProcessTracker" + Process.GetCurrentProcess().Id;
_jobHandle = CreateJobObject(IntPtr.Zero, jobName);
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION {
// This is the key flag. When our process is killed, Windows will automatically
// close the job handle, and when that happens, we want the child processes to
// be killed, too.
LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
};
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info };
var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
var extendedInfoPtr = Marshal.AllocHGlobal(length);
try {
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(_jobHandle, JobObjectInfoType.ExtendedLimitInformation,
extendedInfoPtr, (uint)length)) {
throw new Win32Exception();
}
} finally {
Marshal.FreeHGlobal(extendedInfoPtr);
}
}