在这个论坛上,将“乔什”归功。
Application.Quit()并且
Process.Kill()是可能的解决方案,但已证明是不可靠的。当主应用程序死亡时,您仍然可以运行子进程。我们真正想要的是子进程在主进程死亡后立即死亡。
解决方案是使用“作业对象” http://msdn.microsoft.com/zh-
cn/library/ms682409(VS.85).aspx。
这个想法是为您的主应用程序创建一个“作业对象”,并向该作业对象注册子进程。如果主进程终止,则操作系统将负责终止子进程。
public enum JobObjectInfoType{ AssociateCompletionPortInformation = 7, BasicLimitInformation = 2, BasicUIRestrictions = 4, EndOfJobTimeInformation = 6, ExtendedLimitInformation = 9, SecurityLimitInformation = 5, GroupInformation = 11}[StructLayout(LayoutKind.Sequential)]public struct SECURITY_ATTRIBUTES{ public int nLength; public IntPtr lpSecurityDescriptor; public int bInheritHandle;}[StructLayout(LayoutKind.Sequential)]struct JOBOBJECT_BASIC_LIMIT_INFORMATION{ public Int64 PerProcessUserTimeLimit; public Int64 PerJobUserTimeLimit; public Int16 LimitFlags; public UInt32 MinimumWorkingSetSize; public UInt32 MaximumWorkingSetSize; public Int16 ActiveProcessLimit; public Int64 Affinity; public Int16 PriorityClass; public Int16 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 UInt32 ProcessMemoryLimit; public UInt32 JobMemoryLimit; public UInt32 PeakProcessMemoryUsed; public UInt32 PeakJobMemoryUsed;}public class Job : IDisposable{ [Dllimport("kernel32.dll", CharSet = CharSet.Unipre)] static extern IntPtr CreateJobObject(object a, string lpName); [Dllimport("kernel32.dll")] static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength); [Dllimport("kernel32.dll", SetLastError = true)] static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); private IntPtr m_handle; private bool m_disposed = false; public Job() { m_handle = CreateJobObject(null, null); JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION(); info.LimitFlags = 0x2000; 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); if (!SetInformationJobObject(m_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); } #region IDisposable Members public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion private void Dispose(bool disposing) { if (m_disposed) return; if (disposing) {} Close(); m_disposed = true; } public void Close() { Win32.CloseHandle(m_handle); m_handle = IntPtr.Zero; } public bool AddProcess(IntPtr handle) { return AssignProcessToJobObject(m_handle, handle); }}看着构造函数…
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();info.LimitFlags = 0x2000;
这里的关键是正确设置作业对象。在构造函数中,我将“限制”设置为0x2000,这是的数字值
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE。
MSDN将该标志定义为:
当作业的最后一个句柄关闭时,导致与该作业关联的所有进程终止。
设置好此类后,您只需在作业中注册每个子进程。例如:
[Dllimport("user32.dll", SetLastError = true)]public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);Excel.Application app = new Excel.ApplicationClass();uint pid = 0;Win32.GetWindowThreadProcessId(new IntPtr(app.Hwnd), out pid); job.AddProcess(Process.GetProcessById((int)pid).Handle);


