gpt4 book ai didi

c - WTSRegisterSessionNotification 导致进程挂起

转载 作者:行者123 更新时间:2023-11-30 15:03:03 24 4
gpt4 key购买 nike

我遵循了“简单的窗口”tutorial来自 WinProg 网站。

当教程中的代码在没有 C 运行时库的情况下编译时,一切似乎都按预期工作。窗口已创建并向用户可见显示。

如果我通过按关闭按钮关闭窗口,该窗口将被销毁并且进程将退出 - 该进程不再在本地计算机上运行。

但是,当我链接到 WTS 库并添加对 WTSRegisterSessionNotification 函数的调用时,该进程在关闭其相应窗口后继续在本地计算机上运行。

此行为似乎仅在调用 WTSRegisterSessionNotification 后从 WinMain 返回时才会发生。

我的猜测是 WTSRegisterSessionNotification 创建某种永远不会被通知退出的工作线程。从 WinMain 返回似乎不会导致 ExitProcess 调用,可能是因为代码是在没有 C 运行时库的情况下编译的。

从 WinMain 返回之前调用 ExitProcess 可以避免该问题。但这感觉不是处理这种情况的正确方法。

我的问题是:是否有一个我忽略的 WTS API 函数可以/应该在从 WinMain 返回之前调用,以确保进程退出?

代码示例:

#include <windows.h>
#include <wtsapi32.h>

const char g_szClassName[] = "myWindowClass";

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch (msg)
{
case WM_WTSSESSION_CHANGE:
if (wParam == WTS_SESSION_LOCK)
OutputDebugString( "current session got locked" );
else if (wParam == WTS_SESSION_UNLOCK)
OutputDebugString( "current session got unlocked" );
break;
case WM_CLOSE:
DestroyWindow( hwnd );
break;
case WM_DESTROY:
WTSUnRegisterSessionNotification( hwnd );
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hwnd, msg, wParam, lParam );
}
return 0;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;

//Step 1: Registering the Window Class
wc.cbSize = sizeof( WNDCLASSEX );
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );

if (!RegisterClassEx( &wc ))
{
MessageBox( NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}

// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL );

if (hwnd == NULL)
{
MessageBox( NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}

if (!WTSRegisterSessionNotification( hwnd, NOTIFY_FOR_THIS_SESSION ))
{
MessageBox( NULL, "Register Session Notification Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}

ShowWindow( hwnd, nCmdShow );
UpdateWindow( hwnd );

// Step 3: The Message Loop
while (GetMessage( &Msg, NULL, 0, 0 ) > 0)
{
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
return Msg.wParam;
}

编译器命令行:

/GS- /TC /GL /analyze- /W4 /Gy /Zc:wchar_t /Gm- /O1 /Ob2 /Fd"Release\vc100.pdb" /fp:fast /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /errorReport:prompt /WX- /Zc:forScope /GR- /Gd /Oy /Oi /MD /Fa"Release\" /nologo /Zl /Fo"Release\" /Os 

链接器命令行:

/OUT:"C:\Users\treintje\Documents\Visual Studio 2015\Projects\sample\Release\sample.exe" /MANIFEST:NO /LTCG /NXCOMPAT /PDB:"C:\Users\treintje\Documents\Visual Studio 2015\Projects\sample\Release\sample.pdb" /DYNAMICBASE:NO "kernel32.lib" "user32.lib" "wtsapi32.lib" /ALLOWISOLATION /MACHINE:X86 /ENTRY:"WinMain" /OPT:REF /INCREMENTAL:NO /PGD:"C:\Users\treintje\Documents\Visual Studio 2015\Projects\sample\Release\sample.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"Release\sample.exe.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /NODEFAULTLIB /TLBID:1

最佳答案

The problem could be avoided by calling ExitProcess before returningfrom WinMain. But this doesn't feel like the proper way to deal withthe situation.

退出过程必须直接或间接调用ExitProcess。这是绝对正确的做法,也是强制性的。当您使用CRT时,WinMain并不是应用程序的真正入口点 - 它是从WinMainCRTStartup调用的,而WinMainCRTStartup又调用了ExitProcess。如果您不使用CRT - 您必须直接调用ExitProcess

从 Windows 10(确切地说是 1607 版本,但可能是以前的版本)开始,存在一个新功能 - 用于 dll 加载的“并行加载器”。现在,当您的进程中加载​​任何 dll(ntdllkernel32kernelbase 除外)时,系统会创建工作线程来“并行”加载 dll ”。即使您运行一个非常简单的程序 - 例如 WinMain 中的单个 MessageBox - 但不调用 Exitprocess,您的进程不会退出,但仍会存活 30-60 秒 - dll 加载器工作线程(LdrpWorkCallback) >) 有 30 秒空闲超时,之后将退出。

关于c - WTSRegisterSessionNotification 导致进程挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40854000/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com