Win32 c++ openprocess应该返回null,如果用户已经退出应用程序,但没有
Win32 C++ OpenProceess should return null if user has exited application but doesnt?
我有一个程序(作为后台进程运行),我在其中安装了一个钩子来捕获EVENT_SYSTEM_FOREGROUND事件(即-当用户在窗口之间切换时)。为钩子注册的回调基本上记录了用户从切换到的应用程序(进程exe文件名)以及他们将切换到的应用程序。
我想添加一些代码来检查他们从切换到的应用程序是否仍然活跃(如果不是,我们假设他们已经关闭了它,这就是将新窗口带入前台的原因)。我正在测试它的存在,尝试使用OpenProcess
创建前一个PID的句柄。 //Check prev pid still exists - if not, assume the previous app has been closed
HANDLE hPrevProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,g_prevPid);
if (hPrevProc==NULL){
prevProcStillRunning=false;
}
else{
CloseHandle(hPrevProc);
}
上面代码的假设:
g_prevPid填充了一个PID -我已经验证了这个
prevProcStillRunning已初始化为true
上面代码的问题是,由于某种原因,即使用户退出了应用程序(例如notepad.exe)。在它们退出后的10秒内,这个测试仍然通过(即hPrevProc被初始化)。即使我可以在任务管理器中看到Notepad.exe进程已经消失(是的,我只打开了一个实例),不知何故,OpenProcess行仍然可以得到该PID的句柄。我猜不知何故PID实际上仍然存在,但它可能处于其终止的状态。我发现,如果这段代码再被调用几次,最终它将返回null。
我想找出一个更好的方法,我可以测试hPrevProc是否仍然是活跃的。我试图使用GetExitCodeProcess函数来测试这一点,但这似乎只是给我PID,我甚至不确定这在任何情况下是否是正确的方法。
感谢任何帮助。
进程终止后,至少在它有一个打开的句柄时,它在系统中存在。
了解进程是否仍然处于活动状态的唯一万无一失的方法是:
- 确保进程不能退出代码STILL_ACTIVE (259)
- 尝试打开进程(
OpenProcess
)->如果不能,则被终止 - 读取退出进程代码(
GetExitCodeProcess
) ->如果不是STILL_ACTIVE,则进程终止。
你的代码可以变成:
//Check prev pid still exists - if not, assume the previous app has been closed
HANDLE hPrevProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,g_prevPid);
if (hPrevProc==NULL){
prevProcStillRunning=false;
}
else{
DWORD cr;
if ((GetExitCodeProcess(hPrevProc, &cr) == 0) || (cr != STILL_ACTIVE)) {
prevProcStillRunning=false;
}
CloseHandle(hPrevProc);
}
无论如何,关闭GUI应用程序涉及不同的步骤:
- GUI元素被销毁
- 消息循环结束
- 最终应用程序可以执行后台操作(将状态保存到文件等)
- 主过程返回退出码
- 系统知道应用程序被终止
事件将在主窗口关闭时发送,这可能在应用程序实际停止之前发生。Firefox就是一个很好的例子。如果您关闭窗口并立即尝试启动一个新进程,您将得到一个错误,因为即使UI消失了,进程仍然没有终止。更糟糕的是,当你关闭UI时,你会发现应用程序只是进入后台,并允许用户通过任务栏状态区图标上的动作再次打开UI (Shell_NotifyIcon
及其回调)。这对于在后台工作的其他应用程序的服务(网络服务器、防火墙等)来说很常见。在这种情况下,UI消失了,但是进程不会终止。
TL/DR: UI分离到拥有它的进程终止之间的时间是可变的,取决于系统负载和进程关闭UI后的后台活动。你可以尝试使用延迟,但我不能保证任何事情。
可能某些进程(也许是您的?)仍然持有该进程的有效句柄。在对所有句柄调用CloseHandle之前,系统维护允许访问其进程数据的内部记录。这很重要,因为正如你所说,必须有可能在关闭的进程上调用GetExitCodeProcess,也有人可能想用WaitForSingleObject等待它停止。
也要小心pid,它们可以被重用——所以理论上你可以在其他新打开的进程上调用OpenProcess。
至于检查给定的进程是否不是僵尸,你可以尝试用EnumWindows枚举顶级窗口,并检查它们是否与给定的PID相关联(使用GetWindowThreadProcessID获取窗口的PID)。
- C++控制台应用程序阻止退出
- boost::asio::io_service 在线程中,不会在应用程序退出时退出
- 我在哪里编写在退出 C++ 窗口窗体应用程序之前执行的代码部分
- 正确退出 gtkmm 应用程序
- OpenGL 应用程序退出,退出代码为 -1073741515 (0xC0000135)
- 即使主窗口关闭,也不会退出应用程序
- 对 QMainWindow 使用 std::unique_ptr 时退出时出现 QT 应用程序分段错误
- 我如何使Ctrl Q退出一个没有Menubar的QT5应用程序
- C++11 监视器类,测试应用程序不想退出
- 仅在我退出应用程序后,使用Cout.write()函数在控制台上打印字符串
- 当我要退出应用程序时,如何在QT中自动调用destructor
- 在另一个线程正在运行的情况下退出应用程序时出错
- 在退出应用程序时安全退出Qt线程
- c++允许后台线程在退出应用程序之前完成
- QT/C++,OS X:退出应用程序时可选择隐藏(),以便应用程序继续运行,并在单击dock中的图标后再次显示
- 退出应用程序时崩溃
- 在某些设备上退出应用程序后仍保留进程
- 退出应用程序前关闭线程
- Win32 c++ openprocess应该返回null,如果用户已经退出应用程序,但没有
- 日志文件不可见,除非用户退出应用程序