一个没有UI的ftp server程序,为响应关机消息,我使用RegisterClass、CreateWindowEx创建了一个隐藏窗口接受WM_QUERYENDSESSION、WM_ENDSESSION消息。下面是测试代码:
LRESULT CALLBACK ShutdownDetectorWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_QUERYENDSESSION)
{
MessageBoxA(0, 0, 0, 0);
return TRUE;
}
else if (message == WM_ENDSESSION)
{
MessageBoxA(0, 0, 0, 0);
return TRUE;
}
else if (message == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
else if (message == WM_CHAR)
{
MessageBoxA(0, 0, 0, 0);
return TRUE;
}
else
{
return DefWindowProcA(hwnd, message, wParam, lParam);
}
}
DWORD WINAPI Rundll32DetectLogoffThread(LPVOID lpParam)
{
HINSTANCE *lpInstance = (HINSTANCE*)lpParam;
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = *lpInstance;
wndclass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursorA(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpfnWndProc = ShutdownDetectorWndProc;
wndclass.lpszClassName = "ShutdownDetector";
if (!RegisterClassA(&wndclass)) {
return 1;
}
hwnd = CreateWindowExA(0,
wndclass.lpszClassName, // window class name
"", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
*lpInstance, // program instance handle
NULL);
if (!hwnd) {
return 2;
}
ShowWindow(hwnd, SW_HIDE);
UpdateWindow(hwnd);
while (GetMessageA(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return 0;
}
编译为EXE的时候,关机时正确的收到了消息,弹出了对话框。
但是,编译为DLL,使用rundll32执行的时候无法收到WM_QUERYENDSESSION、WM_ENDSESSION消息。但是,可以收到WM_CHAR消息。
请问这是为什么?
终于找到了原因。
其实我贴出来的代码并没有问题。不知道有没有人注意,我的Rundll32DetectLogoffThread是一个线程回调函数,所以我其实是用CreateThread新建了一个线程在接收消息。
测试结果是,只有在rundll32入口函数那个线程里,才能接收到关机消息,新建的线程收不到。但是,普通EXE新建的线程好像又可以收到。
为什么会这样还不知道,但问题总算是解决了。
看看rundll进程 它可能是system进程 不在当前用户session