使用Win32监视打开的程序

zze*_*man 7 c++ windows winapi monitoring

我搜索了网络和各种论坛,但是我找不到一件事,如果持续监控打开的程序,然后关闭另一个程序(不是被监控的程序),如果被监控的程序发生了什么.

例如,假设已经打开了一个记事本窗口,然后用户或其他程序打开一个Windows资源管理器窗口.我想知道如何关闭记事本窗口而不与Windows资源管理器窗口交互(除了意识到它确实打开),以及如果用户关闭Windows资源管理器窗口,关闭记事本窗口.

提前致谢!:d

Mic*_*eyn 8

在Windows上,您可以使用PSAPI(进程状态API)来了解进程何时启动和终止.该EnumProcesses功能可以给你这个信息.

确定进程终止的更可靠方法(因为进程ID可以重用)是等待其进程句柄(您将需要SYNCHRONIZE访问权限),您可以使用OpenProcess和从EnumProcesses获得的进程ID 来获取该进程句柄.

要终止进程,总会有TerminateProcess.要调用TerminateProcess,您需要具有PROCESS_TERMINATE访问权限的进程句柄.所有这些都假定您具有在要终止的进程上执行这些操作所需的权限.

  • 请注意,TerminateProcess是一个大锤.如果您使用它来"关闭资源管理器窗口",您将最终终止exlporer.exe,它将关闭所有*资源管理器窗口和任务栏.在记事本上使用它,它将使该过程终止,并且还会丢失所做的但未保存的任何编辑:它不会干净地关闭一个过程,它会彻底终止它.有关采取以流程为中心的方法的其他警告,请参阅我在其他地方的答案. (2认同)

Bre*_*McK 5

需要注意的一点是,流程和程序 - 或者至少是用户视为程序的东西 - 不一定是同一件事.

如果您使用PSAPI获取所有正在运行的进程的列表,您将看到很多后台进程根本不对应于打开的窗口.还有一种情况是单个进程可以打开多个顶级窗口.因此,虽然你有像记事本这样的简单案例,其中一旦notepad.exe进程对应一个记事本窗口,你也会遇到如下情况:

  • 单词,其中一个单词进程处理当前打开的所有单词文档(一个进程,许多窗口)
  • 资源管理器,其中一个exploere.exe进程处理所有打开的资源管理器窗口,以及控制面板窗口和任务栏等.
  • Chrome(和其他浏览器),每个标签都有自己的流程(许多流程,一个窗口!)

使用TerminateProcess可能不是关闭应用程序的最佳方式:它不等同于单击关闭按钮.它强行终止那里的整个过程,然后没有任何机会进行清理.如果你在Word上执行此操作,当它重新启动时,它将进入"恢复模式",并表现为它最后一次没有干净地关闭.如果进程停止响应,最好留作最后的手段.此外,如果您在Word或资源管理器等进程上使用TerminateProcess,您最终将关闭该进程拥有的所有窗口,而不仅仅是一个特定的窗口.

鉴于所有这些,如果你想基本上编写某种程序管理器,你可能最好采用以窗口为中心的方法而不是以流程为中心的方法.而不是监视正在运行的进程,监视顶级应用程序窗口.

有几种方法可以监听对窗口的更改; 使用EVENT_CREATE/DESTROY的SetWinEventHook是监听正在创建或销毁的HWND的一种方法(你需要在这里进行过滤,因为它会告诉你所有的HWND - 以及更多! - 但你只关心顶级的,以及只有应用程序那个).SetWindowsHookEx可能有其他选项可以在这里工作(WH_CBT).您还可以使用EnumWindows列出当前存在的窗口(同样,您需要过滤掉所拥有的对话框和工具提示,当前不可见的HWND等).

给定HWND,如果需要,可以使用GetWindowThreadProcessId获取进程信息.

要关闭窗口,首先尝试发送WM_SYSCOMMAND/SC_CLOSE是最好的事情:这更接近于单击关闭按钮,它为应用程序提供了清理的机会.请注意,某些应用会显示"您确定要关闭吗?" 对话框,如果你最近没有保存 - 再次,它与用鼠标单击关闭按钮一致.