2009-07-16 2 views
4

質問:子供のプロセスツリーのすべてのプロセスを削除するにはどうすればよいですか?その後、WXP(および新しいMSWindows)でC#を使用して[グランド]の子プロセスをすべて終了する方法

  1. は、サーバーからのデータのセットを取得し、
  2. スポーンデータを処理するために、サードパーティ製のユーティリティ、
  3. 戻る:

    私は意志のアプリケーション、C#で書かを持っています結果はサーバーに送られます。

これは問題なく動作します。しかし、実行はを多く消費するので、CPUのに1時間かかることがあります。私のアプリが子プロセスを終了させる機能を追加したいと思います。

私が他の場所で見つけたシンプルなソリューションを作るいくつかの問題があります:

  • マイアプリの子プロセス「A」(InstallAnywhereのEXEと思うが)、実際の処理アプリ「B」(のjavaを生成します。 exe)、これはより多くの子供 "C1" .. "Cn"(のほとんどはもJavaで書かれています)を生成します。
  • 私のアプリケーションの複数のコピー(したがって複数のその子のセット)が同じマシン上で実行されている可能性があります。
  • 子プロセスが私の管理下にないため、今後「D」プロセスがある可能性があります。
  • 私のアプリケーションは、32ビットののMSWindowsの64ビットバージョンで実行する必要があります。

データ損失の問題はありません。プロセスがかなり早く終了する限り、「クリーン」シャットダウンは問題ありません。

答えて

2

私はこのコードであなたの孫を殺すことができると思います。the MSDN forumsです。

public bool killProcess(int pid) 
{ 
    bool didIkillAnybody = false; 
    try 
    { 
    Process[] procs = Process.GetProcesses(); 
    for (int i = 0; i < procs.Length; i++) 
    { 
    didIkillAnybody = GetParentProcess(procsIdea.Id) == pid) && 
            killProcess(procsIdea.Id); 
    } 
    try 
    { 
    Process myProc = Process.GetProcessById(pid); 
    myProc.Kill(); 
    return true; 
    } 
    catch { } 
    } 
    catch (Exception ex) 
    { 
    try 
    { 
    new Logger().Write("Exception caught at JobExecution.killProcess()", ex.Message, System.Diagnostics.EventLogEntryType.Warning, false); 
    } 
    catch { } 
    } 
    return didIkillAnybody; 
} 

private int GetParentProcess(int Id) 
{ 
    int parentPid = 0; 
    using (ManagementObject mo = new ManagementObject("win32_process.handle='" + Id.ToString() + "'")) 
    { 
    mo.Get(); 
    parentPid = Convert.ToInt32(mo["ParentProcessId"]); 
    } 
    return parentPid; 
} 
+1

は別の「C」を生む可能性がこれはうまくいかないかもしれませんが、それは私に正しい答えにつながりました。私はプロセスIDのリストを取得し、次にそれらをトップダウンで削除する必要がありました。私のソリューションは、Process.GetProcesses()を1回通過してツリーを構築し、呼び出し元がトップダウンまたはボトムアップを終了させたり、ツリーのデータだけを使用したりすることができます。 – NVRAM

1

私はJake Pearsonのソリューションをテストしましたが、これは必ずしも機能しません。私は他のプロセス(知られているpidの)ツリーを殺したかったのです。もう1つのプロセスでは、各インスタンス(IE 8 - 複数のプロセス)ごとに別々に実行されているiexplore.exeを使用していました。それは正常に動作しますが、WinAPIでIEウィンドウを隠すために使用すると、動作が停止します。

私はsolution on microsoft.public.dotnet.framework groupを見つけました。現在は正常に動作しています。ジェイクの答えはほとんどの場合役に立ちますが、私は思っています。

+0

これは、ツリーではなく、ArrayList内のすべての子を収集します(不必要に再帰的です)。あなたのソリューションを見つけられたらうれしいですが、私は1つのPInvokesを嫌い、それらをペストのように避けています。 – NVRAM

+0

私はPInvokesも好きではありませんが、残念ながら私はそれをたくさん使う必要があります:/私はこの解決策が他の誰かに役立つことを願っています:) – prostynick

2

次のコードは、私の作品:

private void KillProcessAndChildren(int pid) 
{ 
    using (var searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid)) 
    using (ManagementObjectCollection moc = searcher.Get()) 
    { 
    foreach (ManagementObject mo in moc) 
    { 
     KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"])); 
    } 
    try 
    { 
     Process proc = Process.GetProcessById(pid); 
     proc.Kill(); 
    } 
    catch (ArgumentException) 
    { /* process already exited */ } 
    } 
} 

それは私が持っているシナリオのために働きます。それが他の人にとってもうまくいくかどうか聞いてみたいと思う。ここでは、このサイト上で概説ソリューションに基づいて

+0

うまく動作します。しかし、 'ManagementObjectSearcher'と' ManagementObjectCollection'は使い捨てであるため、 'using'ブロックに置かなければなりません。 – ladenedge

+0

+1。私のために働く。私は将来のユーザーのためにあなたの答えに使用ブロックを編集しました。 –

2

は、それを行うためのコンパクトな方法である:私は最初に「B」を殺さなかった場合、私の場合、「B」で

static public void KillChildren(int parentPid) 
    { 
     foreach (var pid in 
      from ManagementBaseObject m in new ManagementObjectSearcher("select ProcessId from Win32_Process where ParentProcessId=" + parentPid).Get() 
      select Convert.ToInt32(m["ProcessId"])) 
      KillChildren(pid); 
     Process.GetProcessById(parentPid).Kill(); 
    } 
関連する問題