簡體   English   中英

如何在Windows中自動銷毀子進程?

[英]How do I automatically destroy child processes in Windows?

在C ++ Windows應用程序中,我啟動了幾個長時間運行的子進程(當前我使用CreateProcess(...)來執行此操作。

如果主進程崩潰或關閉,我希望子進程自動關閉。

由於需要在“父”崩潰時起作用,因此我認為這需要使用操作系統的某些API /功能來完成。 這樣就清除了所有“子”過程。

我該怎么做呢?

Windows API支持稱為“作業對象”的對象。 以下代碼將創建一個“作業”,該作業被配置為在主應用程序結束時(清理其句柄時)關閉所有進程。 該代碼只能運行一次。

HANDLE ghJob = CreateJobObject( NULL, NULL); // GLOBAL
if( ghJob == NULL)
{
    ::MessageBox( 0, "Could not create job object", "TEST", MB_OK);
}
else
{
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };

    // Configure all child processes associated with the job to terminate when the
    jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
    if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
    {
        ::MessageBox( 0, "Could not SetInformationJobObject", "TEST", MB_OK);
    }
}

然后,在創建每個子進程時,執行以下代碼以啟動每個子進程並將其添加到作業對象:

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;

// Launch child process - example is notepad.exe
if (::CreateProcess( NULL, "notepad.exe", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
    ::MessageBox( 0, "CreateProcess succeeded.", "TEST", MB_OK);
    if(ghJob)
    {
        if(0 == AssignProcessToJobObject( ghJob, processInfo.hProcess))
        {
            ::MessageBox( 0, "Could not AssignProcessToObject", "TEST", MB_OK);
        }
    }

    // Can we free handles now? Not sure about this.
    //CloseHandle(processInfo.hProcess); 
    CloseHandle(processInfo.hThread);
}

VISTA注意:如果您在Vista上遇到AssignProcessToObject()的訪問被拒絕的問題,請參閱Vista上的AssignProcessToJobObject始終返回“拒絕訪問”

一個有點棘手的解決方案是將父進程作為調試器附加到每個子進程(使用DebugActiveProcess )。 當調試器終止時,其所有調試進程也將終止。

更好的解決方案(假設您也編寫了子進程)是讓子進程監視父進程,並在父進程消失時退出。

Windows Job Objects聽起來是一個不錯的起點。 Job Object的名稱必須是眾所周知的,或傳遞給子代(或繼承該句柄)。 當家長死亡時,需要通過失敗的IPC“心跳”或僅在家長的進程句柄上的WFMO / WFSO來通知孩子。 屆時,任何子進程都可以使用TermianteJobObject降低整個組的工作效率。

您可以保持單獨的監視程序運行。 它的唯一任務是觀察當前的過程空間以發現您所描述的情況。 它甚至可以在崩潰后重新啟動原始應用程序,或向用戶提供不同的選項,收集調試信息等。只需嘗試使其足夠簡單即可,您就不需要第二個看門狗來監視第一個。

您可能必須保留啟動進程的列表,並在退出程序時將其一一殺死。 我不確定在C ++中執行此操作的具體細節,但這並不難。 困難的部分可能是確保在應用程序崩潰時關閉子進程。 .Net能夠添加一個功能,該功能在發生未處理的異常時被調用。 我不確定C ++是否提供相同的功能。

您可以將每個進程封裝在C ++對象中,並在全局范圍內保留它們的列表。 析構函數可以關閉每個進程。 如果程序正常退出但崩潰了,那么所有的賭注都關閉了,這樣就可以正常工作。

這是一個粗略的示例:

class myprocess
{
public:
    myprocess(HANDLE hProcess)
        : _hProcess(hProcess)
    { }

    ~myprocess()
    {
        TerminateProcess(_hProcess, 0);
    }

private:
    HANDLE _hProcess;
};

std::list<myprocess> allprocesses;

然后,每當啟動一個時,調用allprocessess.push_back(hProcess);。

就在我的頭頂上:

  • 您是否考慮過使用線程而不是進程?
  • 嘗試將主線程/​​進程的句柄傳遞給子進程,並使它們在該句柄上等待。 這適用於線程,因為等待線程句柄一直等到該線程完成並退出。 不太確定它是否適用於進程,應簽出MSDN進行驗證。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM