12

これは以前に尋ねられましたが、コードで決定的な答えを見つけることができません。

プロセス ProcessA (PID 1234) を開きます。このプロセスは、子プロセス ProcessAB (PID 5678) を開きます。完了したら、ProcessA を終了しますが、まだ ProcessAB が残っています。

プロセスツリー全体を終了するにはどうすればよいですか? つまり、開いたプロセスを終了すると、関連するすべてのプロセスも終了することを確認するにはどうすればよいですか?

ありがとう

コードは大歓迎です。

4

7 に答える 7

11

「ジョブ」内のプロセスのグループ化については、このスレッドを確認してください。

それがうまくいかない場合、自家製のアプローチは次のようになります。

  1. メイン プロセス ID を取得する
  2. CreateToolhelp32Snapshotを呼び出して、システム上のすべてのプロセスを列挙します。
  3. 各プロセスの PROCESSENTRY32 構造体の th32ParentProcessID メンバーを確認し、親 ID と一致する場合は、プロセスを終了します ( TerminateProcessを使用) 。
  4. すべての子プロセスが終了したら、メイン プロセスを終了します。

サンプルコード:

    DWORD myprocID = 1234; // your main process id

PROCESSENTRY32 pe;

memset(&pe, 0, sizeof(PROCESSENTRY32));
pe.dwSize = sizeof(PROCESSENTRY32);

HANDLE hSnap = :: CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (::Process32First(hSnap, &pe))
{
    BOOL bContinue = TRUE;

    // kill child processes
    while (bContinue)
    {
        // only kill child processes
        if (pe.th32ParentProcessID == myprocID)
        {
            HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);

            if (hChildProc)
            {
                ::TerminateProcess(hChildProc, 1);
                ::CloseHandle(hChildProc);
            }               
        }

        bContinue = ::Process32Next(hSnap, &pe);
    }

    // kill the main process
    HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID);

    if (hProc)
    {
        ::TerminateProcess(hProc, 1);
        ::CloseHandle(hProc);
    }       
}
于 2009-07-23T17:49:53.287 に答える
5

ジョブ オブジェクトを使用します。

これは、Windows が提供する UNIX の「プロセス グループ」に最も近いものです。

ジョブ オブジェクトを使用すると、子プロセス (およびそのすべての子プロセス) をまとめて管理できることを示すことができます。殺されたからです。UNIX とは異なり、この記事の執筆時点では「ジョブ オブジェクト」はネストできません。つまり、親が子のジョブ オブジェクトを作成すると、その子のすべての子はジョブ オブジェクトを使用できなくなります (これは、1 レベルのサブ ディレクトリしか許可しないファイル システムのように、IMHO の / 重大な制限です)。

于 2011-05-26T12:06:40.123 に答える
3

ALLで木全体を殺すために!!! チャイルズ:

bool __fastcall KillProcessTree(DWORD myprocID, DWORD dwTimeout)
{
  bool bRet = true;
  HANDLE hWnd;
  PROCESSENTRY32 pe;

  memset(&pe, 0, sizeof(PROCESSENTRY32));
  pe.dwSize = sizeof(PROCESSENTRY32);

  HANDLE hSnap = :: CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

  if (::Process32First(hSnap, &pe))
  {
    BOOL bContinue = TRUE;

    // kill child processes
    while (bContinue)
    {
      if (pe.th32ParentProcessID == myprocID)
      {
        ShowMessage ("Gleich - KILL PID: " + AnsiString(pe.th32ProcessID));

        // Rekursion
        KillProcessTree(pe.th32ProcessID, dwTimeout);

        HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);

        if (hChildProc)
        {
          GetWindowThreadProcessId(hWnd, &myprocID);
          // CLOSE Message s
          PostMessage(hWnd, WM_CLOSE, 0, 0) ;

          if (WaitForSingleObject(hChildProc, dwTimeout) == WAIT_OBJECT_0)
            bRet = true;
          else
          {
            bRet = TerminateProcess(hChildProc, 0);
          }
          ::CloseHandle(hChildProc);
        }
      }
      bContinue = ::Process32Next(hSnap, &pe);
    }

    // kill the main process
    HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID);

    if (hProc)
    {
        ::TerminateProcess(hProc, 1);
        ::CloseHandle(hProc);
    }
  }
  return bRet;
}
于 2010-01-28T10:42:23.293 に答える
0

@mjmarshの回答は、自作の場合には再帰が必要です。それ以外の場合は正しいものです。可能な場合は、ジョブ オブジェクトを作成する方が以下よりも優れています。

void KillProcessTree(DWORD myprocID)
{
    PROCESSENTRY32 pe;

    memset(&pe, 0, sizeof(PROCESSENTRY32));
    pe.dwSize = sizeof(PROCESSENTRY32);

    HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (::Process32First(hSnap, &pe))
    {
        do // Recursion
        {
            if (pe.th32ParentProcessID == myprocID)
                KillProcessTree(pe.th32ProcessID);
        } while (::Process32Next(hSnap, &pe));
    }


    // kill the main process
    HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID);

    if (hProc)
    {
        ::TerminateProcess(hProc, 1);
        ::CloseHandle(hProc);
    }
}
于 2016-03-18T16:45:24.523 に答える
0

How To Kill a Process Treeがありますが、それはC#にあります。それをCに移植するのはそれほど難しくないと思います。

NtQueryInformationProcess 関数TerminateProcess 関数を参照してください。

于 2009-07-23T17:46:06.697 に答える
-1

以下は Linux の場合ですが、Windows の適応に役立つことを願っています。

fork() すると、子プロセスの pid である戻り値が保存され、親が終了しようとしているときに、pid を kill() します。

複数の子プロセスがある場合は、kill をプロセス グループに送信できます。デフォルトでは、子プロセスは親プロセスと同じ pgid を持ちます。

于 2009-07-23T17:42:39.450 に答える