C++ 如何处理;“结束任务”;从后台进程上的Windows任务管理器?

C++ 如何处理;“结束任务”;从后台进程上的Windows任务管理器?,c++,c,windows,C++,C,Windows,我编写了一个简单的测试程序(TestProgram.exe)来学习如何处理CTRL\u CLOSE\u事件,下面是我的观察结果和问题: 1) 当我双击TestProgram.exe启动它时,如果我现在转到任务管理器,TestProgram.exe将列在“应用程序”下。当我在TestProgram.exe上执行“结束任务”时,将调用我的CTRL\u CLOSE\u事件处理程序 但是 2) 当我打开一个命令提示符并启动TestProgram.exe时,它会列在任务管理器下的“后台进程”下,并且在同一

我编写了一个简单的测试程序(TestProgram.exe)来学习如何处理CTRL\u CLOSE\u事件,下面是我的观察结果和问题:

1) 当我双击TestProgram.exe启动它时,如果我现在转到任务管理器,TestProgram.exe将列在“应用程序”下。当我在TestProgram.exe上执行“结束任务”时,将调用我的CTRL\u CLOSE\u事件处理程序

但是

2) 当我打开一个命令提示符并启动TestProgram.exe时,它会列在任务管理器下的“后台进程”下,并且在同一进程上执行“结束任务”不会导致CTRL\u CLOSE\u事件

我的实际应用程序如上述案例2)所述。我想在用户在我的应用程序上执行结束任务时进行一些清理(在任务管理器的后台进程下列出)

谢谢,
Krishna

一般来说,当一个进程被列为“应用程序”时,这意味着任务管理器检测到该进程有一个GUI和一个“结束任务”在GUI上,将首先尝试通过标准的
WM_close
和/或
WM_QUIT
消息优雅地关闭GUI,然后通过
TerminateProcess()
诉诸暴力终止GUI进程。另一方面,在“后台进程”上执行“结束任务”将立即执行暴力终止


因此,在您的情况下,双击.exe文件会产生一个新的专用控制台进程,该进程只运行您的应用程序,因此控制台的GUI会被标记为“应用程序”,但当您首先打开控制台窗口并通过命令行执行.exe时,您的应用程序正在现有控制台中运行,并且正在共享控制台的原始GUI,因此您的应用程序没有自己的GUI,因此会被标记为“后台进程”。

当进程终止(未关闭)时,除非您通过挂接或在任务管理器进程中开始挂接,否则无法执行任何操作,其工作原理示例:

#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;
}
#包括
#将其包含在任务管理器流程中,但未对其进行测试。但这种方法工作过度且不安全,一些AV产品可能会将其检测为有害节目

一个简单的解决方案是按照@Martin James的建议清理程序启动。在程序启动时,创建一个文件或使用注册表存储一些值,如
0
,如果程序已关闭,则收到
WM\u CLOSE
如果是GUI或
CTRL\u CLOSE\u事件
如果关闭命令提示符,则进行清理并存储
1

在下一次启动时,如果该值仍然为
0
,则检查该值,这意味着如果程序未正确关闭,则执行清理,如果为
1
,则无需清理,存储
0
,然后继续


许多程序使用此方法来检测程序是否正确关闭。

哪个版本的Windows?应用程序重新启动时可以进行清理吗?一般来说,如果用户从任务管理器中杀死你的应用程序,它就死了。对于安全性来说,没有什么是可以接受的——拥有足够特权的用户必须能够在没有通知的情况下停止应用程序。我理解。但我在某个地方读到,应用程序有一些时间,大约10秒的时间来做任何必要的清理。另外,正如我最初提到的,为什么我能够在案例1中处理它,而不能在案例2中处理它?非常感谢!非常有用的回答。关于钩子TerminateProcess的代码还有一个问题。您是如何选择地址0x68和0xc3的?@kristrevirus这些不是地址,它们是汇编指令的操作码,spicily和.Aah!请原谅我的无知。不幸的是,在通过任务管理器结束任务时没有调用处理程序。至少不是在我的小控制台测试应用程序中。显然,在这种情况下使用的不是TerminateProcess。