在C#中實現子進程隨父進程結束的機制
使用System.Diagnostics.Process
類別建立進程時,確保子進程在父應用程式崩潰時也終止至關重要。然而,在某些情況下,例如透過任務管理器終止應用程式時,這種行為並非自動實現。
為了解決這個問題,我們可以利用Windows作業系統提供的「作業物件」。透過為父應用程式建立作業物件並將子進程註冊到其中,我們可以在進程之間建立依賴關係。這確保了當父進程終止時,作業系統會自動終止子進程。
作業物件的實作
以下程式碼示範如何建立作業物件並將子程序與其關聯:
<code class="language-csharp">public class Job : IDisposable { private IntPtr m_handle; private bool m_disposed = false; public Job() { m_handle = CreateJobObject(IntPtr.Zero, null); // 修正:使用IntPtr.Zero JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION(); info.LimitFlags = 0x2000; // 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); if (!SetInformationJobObject(m_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) throw new Exception($"无法设置信息。错误代码:{Marshal.GetLastWin32Error()}"); // 使用插值字符串 Marshal.FreeHGlobal(extendedInfoPtr); // 释放非托管内存 } public bool AddProcess(IntPtr handle) { return AssignProcessToJobObject(m_handle, handle); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual 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; } }</code>
建構函式中的關鍵行是:
<code class="language-csharp">info.LimitFlags = 0x2000;</code>
這設定了JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
標誌,該標誌指定當作業關閉時,與該作業關聯的所有進程都應終止。
建立作業物件後,可以使用AddProcess
方法將子行程與其關聯。例如下:
<code class="language-csharp">using Microsoft.Office.Interop.Excel; // 确保引用了Excel互操作库 // ...其他代码... Excel.Application app = new Excel.ApplicationClass(); uint pid = 0; Win32.GetWindowThreadProcessId(new IntPtr(app.Hwnd), out pid); Process process = Process.GetProcessById((int)pid); job.AddProcess(process.Handle); // ...其他代码... // 记得释放COM对象 Marshal.ReleaseComObject(app); app = null; // ...其他代码...</code>
透過將子程序註冊到作業對象,可以確保即使作業系統突然終止,它們也會自動終止。 程式碼中加入了錯誤處理和資源釋放,提高了程式碼的健全性和可靠性。 同時,確保正確引用了Excel互通函式庫。
注意: 此方法依賴Windows作業系統提供的作業物件功能,僅適用於Windows平台。 此外,需要加入對kernel32.dll
的P/Invoke
聲明(Win32
類),程式碼中省略了這部分,需要自行補充。 並且需要處理潛在的異常,例如進程不存在或權限不足等情況。 最後,記得釋放COM對象,避免資源外洩。
以上是C# 中如何確保父應用程式崩潰時子進程終止?的詳細內容。更多資訊請關注PHP中文網其他相關文章!