ホームページ > バックエンド開発 > C++ > 親アプリケーションがC#でクラッシュしたときに子どものプロセスが終了するようにする方法は?

親アプリケーションがC#でクラッシュしたときに子どものプロセスが終了するようにする方法は?

Susan Sarandon
リリース: 2025-01-25 04:45:10
オリジナル
269 人が閲覧しました

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 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート