首页 >后端开发 >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