How to handle “End Task” from Windows Task Manager on a background process?

前端 未结 2 1459
盖世英雄少女心
盖世英雄少女心 2020-12-21 13:35

I wrote a simple test program (TestProgram.exe) to learn how to handle the CTRL_CLOSE_EVENT and here are my observations and my question:

1) When I double click Test

相关标签:
2条回答
  • 2020-12-21 13:41

    In general, when a process is listed as an "Application", it means Task Manger has detected the process has a GUI, and an "End Task" on a GUI will first attempt to graceful close the GUI via standard WM_CLOSE and/or WM_QUIT messages before then resorting to a brute-force termination of the GUI's process via TerminateProcess(). On the other hand, doing an "End Task" on a "Background Process" will perform a brute-force termination immediately.

    So in your situation, double-clicking on the .exe file results in a new dedicated console process that is running just your app by itself, so the console's GUI gets flagged as an "Application", but when you open a console window first and execute your .exe via the command-line, your app is running within the existing console and is sharing the console's original GUI, so your app does not have its own GUI and thus gets flagged as a "Background Process" instead.

    0 讨论(0)
  • 2020-12-21 14:06

    When a process is terminated (not closed) nothing realy can be done unless you start do some hooking, either by hooking TerminateProcess or NtTerminateProcess in the Task Manger process, example of how it works:

    #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;
    }
    

    This hooks TerminateProcess in the same process, you need to ship it in a DLL and inject it in the Task Maneger process, didn't test it. But this method is overwork and not safe, some AV products may detect it as harmful program.

    A simple solution is to clean up on the program start-up as @Martin James suggested. On your program start-up create a file or use the registry to store some value like 0, if the program was closed, received WM_CLOSE if it's GUI or CTRL_CLOSE_EVENT if you closed the command prompt, you do the clean-up and store 1.

    On the next start-up you you check back that value if it stills 0, this mean do the program was not closed properly, do do the clean up, if it's 1 no need to the clean-up, store 0 and move on.

    Many programs use this method to detect if the program was closed properly.

    0 讨论(0)
提交回复
热议问题