有时候,我们需要创建一个新进程来执行一些额外的事情,同时还需要确保新进程随当前进程一起退出。我们可以用Windows提供的作业对象来完成这件事。
首先我们创建一个作业对象,然后设置JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
这个flag,然后把新创建进程关联到这个作业对象就可以了。这个flag的含义是让作业里的进程在作业对象关闭后就退出,当当前进程退出了,这个对象的句柄就被关闭了,从而实现当前进程退出后,新创建的进程退出的效果。
通过C#进程P/Invoke调用的代码如下:
var job = CreateJobObject(NullRef<SECURITY_ATTRIBUTES>(), null);
var s = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
s.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(job, JobObjectExtendedLimitInformation, AsPointer(ref s), Marshal.SizeOf<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>());
var process = Process.Start("notepad.exe");
AssignProcessToJobObject(job, process.Handle);
通过上面这个代码启动的记事本就会在当前进程退出后退出。
另外还要注意的是,在Windows7之前的系统中,一个进程只能和一个作业关联,如果父进程已经已经和某个作业关联,通过Process.Start
创建的子进程也会和该作业关联,从而导致AssignProcessToJobObject
失败。这种情况下,要在创建进程时附加CREATE_BREAKAWAY_FROM_JOB
参数,防止新创建的子进程和父进程原本关联的作业关联。
PS:通过Visual Studio调试时,创建出来的进程就会和一个作业关联,同时其创建出来的进程会在被调试进程退出时退出。