Я следил за «Простым окном» tutorial с сайта WinProg.WTSRegisterSessionNotification, вызывающий процесс зависания
Когда код из учебника скомпилирован без библиотеки времени выполнения C, все работает так, как планировалось. Окно создается и визуально отображается пользователю.
Если я закрою окно, нажав кнопку закрытия, окно будет уничтожено, и процесс будет завершен - процесс больше не запускается на локальной машине.
Однако, когда я связываюсь с библиотекой WTS и добавляю вызов функции WTSRegisterSessionNotification, процесс продолжается на локальном компьютере после закрытия соответствующего окна.
Такое поведение наблюдается только при возврате из WinMain после вызова WTSRegisterSessionNotification.
Я предполагаю, что WTSRegisterSessionNotification создает какой-то рабочий поток, который никогда не будет уведомлен о выходе. Возврат из WinMain, похоже, не приводит к вызову ExitProcess, вероятно, потому, что код компилируется без библиотеки времени выполнения C.
Проблема может быть устранена вызовом ExitProcess перед возвратом из WinMain. Но это не похоже на правильный способ справиться с ситуацией.
Мой вопрос: есть ли функция 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
Linker Командная строка:
/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
Вы пытались вызвать 'WTSUnRegisterSessionNotification' перед' DestroyWindow'? –
вы должны всегда вызывать 'ExitProcess' (если вы не используете CRT) - и я предлагаю протестировать вашу программу на win 10 (1607) без' WTSUnRegisterSessionNotification' - это выход из процесса, если вы не вызываете 'Exitprocess' – RbMm