У меня есть приложение, задачей которого является запуск и остановка различных других процессов.Завершение процесса Qt: что делает диспетчер задач Windows, что я не?
Проблема в том, что приложения Qt не прекращаются чисто. Окно Qt закрывается, но процесс все еще работает в фоновом режиме, пока не вызывается TerminateProcess(), а затем приложение Qt выходит без очистки.
Я использую this method, как указано Microsoft. Даже Qt source использует этот метод для завершения процессов, за исключением того, что они также отправляют WM_CLOSE в основной поток. Я добавил это к моему приложению, но он все еще закрывает окно, оставляя этот процесс.
Интересно, что если я использую диспетчер задач Windows для «Завершить задачу» («Не завершать процесс»), окно закрывается, и процесс также заканчивается, поэтому я знаю, что это возможно. Если я использую spy ++, я вижу, что основное окно и основной поток принимают сообщения WM_CLOSE из диспетчера задач и моего приложения, но только с помощью диспетчера задач сообщения продолжаются до WM_DESTROY, WM_NCDESTROY и т. Д. И заканчиваются завершением процесса , Эта проблема возникает только с приложениями Qt. Приложения Win32/MFC и т. Д. Прекращают использование моего приложения.
Как вы должны полностью закрыть приложения Qt (предположим, что источник приложения Qt недоступен)?
-------- Редактировать --------
Вот пример кода, который будет воспроизвести проблему. По крайней мере, мне было бы интересно узнать, видят ли другие люди ту же проблему, что и я.
Образец кода начинается с CMake (download here), но любое приложение Qt должно делать.
#include <Windows.h>
#include <iostream>
BOOL CALLBACK TerminateAppEnum(HWND hwnd, LPARAM pid);
int _tmain(int argc, _TCHAR* argv[])
{
char* processName = "C:\\Program Files (x86)\\CMake\\bin\\cmake-gui.exe";
//char* processName = "C:\\Windows\\Notepad.exe";
std::cout << "Creating process \"" << processName << "\"" << std::endl;
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi = {0};
BOOL success = CreateProcess(processName,
"",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi);
if (success)
{
std::cout << "Press any key to cleanly terminate process..." << std::endl;
std::cin.get();
std::cout << "Cleanly terminating process..." << std::endl;
EnumWindows(TerminateAppEnum, (LPARAM)pi.dwProcessId);
PostThreadMessage(pi.dwThreadId, WM_CLOSE, 0, 0);
if (WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0)
{
std::cout << "Success! The process has terminated" << std::endl;
}
else
{
std::cout << "Failed! The process is still running" << std::endl;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
{
std::cout << "Unable to start process (Error " << GetLastError() << ")" << std::endl;
}
std::cout << "Press any key to exit..." << std::endl;
std::cin.get();
return 0;
}
BOOL CALLBACK TerminateAppEnum(HWND hwnd, LPARAM pid)
{
DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);
if (dwPID == (DWORD)pid)
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
return TRUE;
}
QT обычно знает, когда ему нужно выйти, и делает это чисто, за исключением того, если разработчик перепутались, который вы могли бы проверить, посмотрев на (нет) исходный код ... – SirDarius
@SirDarius: Это тоже мой мыслительный процесс, но из всех приложений, которыми управляет эта программа, только у Qt есть эта проблема (всего 3), и все они принадлежат другим авторам. Совпадение? Кроме того, диспетчер задач может их закрыть, но как ..? – parrowdice
Я могу предложить вам попробовать остановить сторонние программы QT с открытым исходным кодом, такие как cmake gui, которые вы могли бы отлаживать, и посмотреть, как он был реализован. – SirDarius