2013-08-26 78 views
2

我寫了一個簡單的測試程序(TestProgram.exe),以瞭解如何處理CTRL_CLOSE_EVENT,這裏是我的意見,我的問題:如何在後臺進程中處理Windows任務管理器中的「結束任務」?

1)當我雙擊TestProgram.exe啓動它,如果我現在去任務管理器,TestProgram.exe列在「應用程序」下。當我在TestProgram.exe上執行「結束任務」時,我的CTRL_CLOSE_EVENT處理程序正在調用。

BUT

2)當我打開命令提示,並啓動TestProgram.exe,它是在「後臺進程」下任務管理器,做一個「結束任務」列在同一不會導致一個CTRL_CLOSE_EVENT。

我的真實應用程序按照上述情況2)中的描述使用。我想在用戶對我的應用程序執行結束任務時進行一些清理操作(在任務管理器中的後臺進程下列出)。

謝謝, 克里希納

+1

哪個版本的Windows? –

+2

你可以做應用程序重新啓動清理?一般來說,如果用戶從任務管理器中殺死你的應用程序,它已經死了。沒有其他安全措施是可以接受的 - 具有足夠權限的用戶必須能夠在沒有通知的情況下停止應用程序。 –

+0

我明白了。但是我在某個地方看過應用程序需要一些時間,大約10秒鐘才能完成必要的清理工作。另外,正如我最初提到的那樣,爲什麼我能夠在情況1下處理它,而不是上面的情況2呢? – Krishna

回答

7

通常,當一個過程被列爲「應用程序」,這意味着任務管理器已檢測的方法具有一個圖形用戶界面,並在GUI將首先嚐試的「結束任務」在通過標準WM_CLOSE和/或WM_QUIT消息優雅地關閉GUI之後,然後通過TerminateProcess()藉助強制終止GUI過程。另一方面,在「後臺進程」上執行「結束任務」將立即執行強力終止。

因此,在您的情況下,雙擊.exe文件會生成一個新的專用控制檯進程,該進程僅運行您的應用程序,因此控制檯的GUI被標記爲「應用程序」,但是當您打開控制檯窗口並通過命令行執行.exe,您的應用程序在現有控制檯中運行並共享控制檯的原始GUI,因此您的應用程序沒有自己的GUI,因此被標記爲「後臺進程」 。

+0

好的解釋! – Krishna

2

當一個進程被終止(未封閉)沒有什麼真的可以做到,除非你開始做一些掛鉤,無論是在任務管理器進程掛鉤TerminateProcessNtTerminateProcess,例如它是如何工作的:

#include <windows.h> 
#include <assert.h> 

BOOL WINAPI MyTerminateProcess(HANDLE hProcess, UINT uExitCode) { 
    MessageBox(NULL, TEXT("Do some cleanup"), NULL, MB_OK); 
    ExitProcess(0); 
    return TRUE; 
} 

#pragma pack(1) 
typedef struct __PATCHDATA { 
    BYTE push; 
    DWORD address; 
    BYTE ret; 
} PATCHDATA; 
#pragma pack() 

int main(int argc, char **argv) { 
    HMODULE hModule; 
    DWORD written; 
    // This struct contains assembly instruction that do: 
    // push address ; 0x68 MyTerminateProcess 
    // ret   ; 0xc3 
    // so the execution will return to our hook 
    PATCHDATA patch = {0x68, (DWORD) MyTerminateProcess, 0xc3}; 

    // remove this code, the program will terminate itself. 
    // TODO: check the memory protection and modify it. 
    WriteProcessMemory(GetCurrentProcess(), 
         TerminateProcess, 
         &patch, 
         sizeof(PATCHDATA), 
         &written); 

    TerminateProcess(NULL, 0); 

    return 0; 
} 

這個鉤子在同一個進程中掛鉤了TerminateProcess,你需要將它發佈到一個DLL中,並且它在Task Maneger進程中沒有測試它。但是這種方法過度且不安全,有些AV產品可能會將其視爲有害程序。

一個簡單的解決方案是按照@Martin James的建議清理程序啓動。在程序啓動時創建文件或使用註冊表來存儲一些值,如0,如果程序關閉,則收到WM_CLOSE如果是GUI或CTRL_CLOSE_EVENT如果關閉了命令提示符,則執行清理並存儲1

在您查覈一下這個值,如果它劇照0在下次啓動時,這意味着你的程序沒有正確關閉,不要做清理,如果它是1無需清理,店0並繼續前進。

許多程序使用此方法來檢測程序是否正確關閉。

+0

非常感謝!非常有用的迴應。一個問題,雖然你的代碼掛鉤TerminateProcess。你是如何選擇地址0x68和0xc3的? – Krishna

+0

@KrisRetroVirus這些不是地址,它們是彙編指令的操作碼,spicily [push imm = 0x68](http://ref.x86asm.net/coder32.html#x68)和[retn = 0xc3](http:// ref .x86asm.net/coder32.html#XC3)。 – 2013-08-27 05:23:21

+0

啊!請原諒我的無知。 – Krishna

相關問題