2017-02-24 51 views
-1

我有C編寫的Win32控制檯程序,需要在一定的時間長度過去終止,即使它仍然很忙。目前,我這樣做:真的殺了當前進程,當時間流逝

static VOID CALLBACK timeout(PVOID a, BOOLEAN b) { ExitProcess(0); } 

...

HANDLE timer = 0; 
    CreateTimerQueueTimer(&timer, 0, timeout, 0, (DWORD)(time_limit * 1000), 
         0, 0); 

這工作正常,在到達時間限制時,該程序在計算上是繁忙的情況下,例如它很容易通過一個測試案例,我在main中放置了一個無限循環。但是,這種情況不起作用,程序只能無限期地停留。這種情況與被父母程序打電話有關,我不知道到底發生了什麼事,並且對此提出了一個單獨的問題。在這裏我的問題是:

有沒有辦法來告訴Windows 真正若干秒,無論什麼後殺死當前的進程?

更新:實驗剛纔WT_EXECUTEINTIMERTHREAD似乎解決了問題。這留下了幾個問題:

  1. 爲什麼那個旗子很重要?

  2. 如果我沒有在程序中使用任何其他時間操作,是否可以忽略警告「該標誌只能用於短期任務或可能影響其他定時器操作」。

  3. 如果有多個選擇標誌就能解決問題,這標誌是它最好用?

+0

退出進程應該*真正*殺死當前進程。恐怕您需要告訴我們更多關於這種情況的信息,這與被父母程序稱爲不知道到底發生了什麼有關。也許提供一個單獨的問題的鏈接? –

+0

@MikeNakis關於父進程發生了什麼的問題是http://stackoverflow.com/questions/42431166/parent-process-exit-causes-child-process-tohang - 如果ExitProcess會完成這項工作,必須表示我的超時功能未被調用;有沒有辦法保證超時功能總是會被調用,不管是什麼? – rwallace

+1

只有在'ExitProcess(0)'之前產生一個'Sleep(time_limit * 1000)'的單獨線程。在當前的設置中,我無法確定,但可能是因爲您設置的計時器依賴於與標準輸入/標準輸出的某些成功交互,並且這不起作用,因爲它們被現在已死的父進程重定向,所以定時器也不起作用。您可以通過在ExitProcess(0)'之前寫入一個長條目來驗證。我敢打賭,你永遠不會看到日誌條目。我敢打賭,如果你使用單獨的線程方法,你會看到它。 –

回答

0

您可以使用SleepEx

掛起當前線程,直到滿足指定條件。當發生以下情況之一執行恢復: 一個I/O完成回調函數被調用, AN異步過程調用(APC)排隊到線程OR 超時間隔過去。

第三,或第一種選擇是你最好的選擇。第一個功能的條件應該是您所期望的情況,無論您的程序如何。或預先配置的時間量。

SleepEx通過ZwTerminateProcessNTDLL.DLL後續。這將確保過程終止,因爲在致電ZwTerminateProcess/Thread之前致電ExitProcess執行事先檢查。在這裏你可以自己打電話並確保終止!您可以通過將GetCurrentProcess()傳遞給參數來填寫ZwTerminateProcessHANDLE參數。或者,您通過ZwQuerySystemInformation->ZwOpenProcess或創建快照(CreateToolhelp32Snapshot ...離開我的頭頂部)然後Process32First->Next->OpenProcess掃描進程列表,獲得HANDLE到遠程進程 - 然後您可以使用ZwTerminateProcess來終止您給定的遠程進程具有SE_DEBUG_PRIVILEGE,並且當前進程正在執行與其他進程相同的完整性級別!

+1

[ZwTerminateProcess](https://msdn.microsoft.com/en-us/library/windows/hardware/ff567115.aspx):*「如果對此函數的調用發生在用戶模式下,則應使用名稱」* * NtTerminateProcess **「而不是」** ZwTerminateProcess **「。」* – IInspectable

+1

不需要使用。簡單的舊TerminateProcess應該工作得很好。 –

+1

@IInspectable NtTerminateProcess指向ZwTerminateProcess,沒有兼容性問題。在我的工作中,我一直在努力工作,並且從未遇到任何問題! – Droopy