首頁 >後端開發 >C++ >C# 中如何確保父應用程式崩潰時子進程終止?

C# 中如何確保父應用程式崩潰時子進程終止?

Susan Sarandon
Susan Sarandon原創
2025-01-25 04:45:10279瀏覽

How to Ensure Child Processes Terminate When the Parent Application Crashes in C#?

在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.dllP/Invoke聲明(Win32類),程式碼中省略了這部分,需要自行補充。 並且需要處理潛在的異常,例如進程不存在或權限不足等情況。 最後,記得釋放COM對象,避免資源外洩。

以上是C# 中如何確保父應用程式崩潰時子進程終止?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn