C++ 终止Qt进程:什么';s Windows任务管理器正在执行此操作I';我不是?

C++ 终止Qt进程:什么';s Windows任务管理器正在执行此操作I';我不是?,c++,windows,qt,winapi,kill-process,C++,Windows,Qt,Winapi,Kill Process,我有一个应用程序,其工作是启动和停止各种其他进程 问题是Qt应用程序并没有完全停止。Qt窗口关闭,但进程仍在后台运行,直到调用TerminateProcess(),然后Qt应用程序退出而不进行清理 我使用的是微软概述的。即使是应用程序也使用该方法来终止进程,除非它们还向主线程发送一个。我也将其添加到了我的应用程序中,但它仍然只是关闭了窗口,离开了流程 我发现有趣的是,如果我使用Windows任务管理器来“结束任务”(而不是“结束进程”),窗口将关闭,进程也将结束,因此我知道这是可能的。如果我使用

我有一个应用程序,其工作是启动和停止各种其他进程

问题是Qt应用程序并没有完全停止。Qt窗口关闭,但进程仍在后台运行,直到调用TerminateProcess(),然后Qt应用程序退出而不进行清理

我使用的是微软概述的。即使是应用程序也使用该方法来终止进程,除非它们还向主线程发送一个。我也将其添加到了我的应用程序中,但它仍然只是关闭了窗口,离开了流程

我发现有趣的是,如果我使用Windows任务管理器来“结束任务”(而不是“结束进程”),窗口将关闭,进程也将结束,因此我知道这是可能的。如果我使用spy++,我可以看到主窗口和主线程都从任务管理器和我的应用程序接收WM_CLOSE消息,但只有使用任务管理器,消息才能继续执行WM_DESTROY、WM_NCDESTROY等,并以进程结束而结束。这个问题只发生在Qt应用程序中。Win32/MFC etc应用程序使用我的应用程序干净地终止

您应该如何干净地关闭Qt应用程序(假设Qt应用程序源不可用)

------编辑-----

下面是一些重现问题的示例代码。至少,我想知道其他人是否也看到了与我相同的问题

示例代码启动CMake(),但任何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;
}
#包括
#包括
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。它有同样的问题-窗口关闭,但进程仍然存在