子プロセスが親プロセスで終了するメカニズムを 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 中国語 Web サイトの他の関連記事を参照してください。