C++ 终止Qt进程:什么';s Windows任务管理器正在执行此操作I';我不是?
我有一个应用程序,其工作是启动和停止各种其他进程 问题是Qt应用程序并没有完全停止。Qt窗口关闭,但进程仍在后台运行,直到调用TerminateProcess(),然后Qt应用程序退出而不进行清理 我使用的是微软概述的。即使是应用程序也使用该方法来终止进程,除非它们还向主线程发送一个。我也将其添加到了我的应用程序中,但它仍然只是关闭了窗口,离开了流程 我发现有趣的是,如果我使用Windows任务管理器来“结束任务”(而不是“结束进程”),窗口将关闭,进程也将结束,因此我知道这是可能的。如果我使用spy++,我可以看到主窗口和主线程都从任务管理器和我的应用程序接收WM_CLOSE消息,但只有使用任务管理器,消息才能继续执行WM_DESTROY、WM_NCDESTROY等,并以进程结束而结束。这个问题只发生在Qt应用程序中。Win32/MFC etc应用程序使用我的应用程序干净地终止 您应该如何干净地关闭Qt应用程序(假设Qt应用程序源不可用) ------编辑----- 下面是一些重现问题的示例代码。至少,我想知道其他人是否也看到了与我相同的问题 示例代码启动CMake(),但任何Qt应用程序都应该这样做C++ 终止Qt进程:什么';s Windows任务管理器正在执行此操作I';我不是?,c++,windows,qt,winapi,kill-process,C++,Windows,Qt,Winapi,Kill Process,我有一个应用程序,其工作是启动和停止各种其他进程 问题是Qt应用程序并没有完全停止。Qt窗口关闭,但进程仍在后台运行,直到调用TerminateProcess(),然后Qt应用程序退出而不进行清理 我使用的是微软概述的。即使是应用程序也使用该方法来终止进程,除非它们还向主线程发送一个。我也将其添加到了我的应用程序中,但它仍然只是关闭了窗口,离开了流程 我发现有趣的是,如果我使用Windows任务管理器来“结束任务”(而不是“结束进程”),窗口将关闭,进程也将结束,因此我知道这是可能的。如果我使用
#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;
}
#包括
#包括
BOOL回调终止penum(HWND-HWND,LPARAM-pid);
int _tmain(int argc,_TCHAR*argv[]
{
char*processName=“C:\\ProgramFiles(x86)\\CMake\\bin\\cmakegui.exe”;
//char*processName=“C:\\Windows\\Notepad.exe”;
好的,解决了
问题源于Qt创建了一个顶级窗口—一个QEventDispatcher
窗口。按照Microsoft概述的过程,此窗口会收到一条WM_CLOSE消息,该消息会关闭该窗口及其线程。之后,当应用程序的主窗口关闭时,不会进行任何清理,进程将保留在sys中tem存储器
有趣的是,通过使用任务管理器,QEventDispatcher不会获得WM_CLOSE消息,因此会保持活动状态,因此当主窗口显示WM_CLOSE消息时,进程会干净地退出。我只能假设在任务管理器中使用了类似的调用,这与它们的调用相反。尽管该文档是上次修订的十多年前的母羊
添加对IsWindowVisible的调用使该程序能够与所有Qt应用程序一起工作,而其他非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);
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)
{
if (IsWindowVisible(hwnd))
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
}
return TRUE;
}
#包括
#包括
BOOL回调终止penum(HWND-HWND,LPARAM-pid);
int _tmain(int argc,_TCHAR*argv[]
{
char*processName=“C:\\ProgramFiles(x86)\\CMake\\bin\\cmakegui.exe”;
//char*processName=“C:\\Windows\\Notepad.exe”;
std::cout QT通常知道什么时候需要退出,并且会很清楚地知道,除非开发人员搞砸了,你可以通过查看(不可用的)源代码来检查…@SirDarius:这也是我的思考过程,但是在这个程序管理的所有应用程序中,只有QT有这个问题(总共3个),它们都是由不同的作者编写的。巧合?此外,任务管理器可以完全关闭它们,但如何关闭它们?我可能建议您尝试停止第三方开源qt程序,例如可以调试的cmake gui,并查看它是如何实现的qt可能是(不正确的)希望wParam和/或lParam有一些特定的值吗?@SirDarius:我刚刚尝试了CMake gui。它有同样的问题-窗口关闭,但进程仍然存在