C++, 如何确定 Windows 进程是否正在运行?
这与 Windows XP 进程有关。
我有一个正在运行的进程,我们将其称为 Process1。 Process1 创建一个新进程 Process2,并保存其 id。
现在,在某个时刻,Process1 希望 Process2 执行某些操作,因此它首先需要确保 Process2 仍然存在,并且用户没有杀死它。
如何检查该进程是否仍在运行? 自从我创建它以来,我就有了进程 ID,我认为有一些类似于 IsProcessIDValid( id ) 的库函数,但我在 MSDN 上找不到它
This is concerning Windows XP processes.
I have a process running, let's call it Process1. Process1 creates a new process, Process2, and saves its id.
Now, at some point Process1 wants Process2 to do something, so it first needs to make sure that Process2 is still alive and that the user has not not killed it.
How can I check that this process is still running?
Since I created it, I have the Process ID, I would think there is some library function along the lines of IsProcessIDValid( id ) but I can't find it on MSDN
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
您可以使用
GetExitCodeProcess
。如果进程仍在运行(或者碰巧以该退出代码退出:( ),它将返回STILL_ACTIVE
(259)。You can use
GetExitCodeProcess
. It will returnSTILL_ACTIVE
(259) if the process is still running (or if it happened to exit with that exit code :( ).如果进程句柄退出,则会收到信号通知。
因此,以下内容将起作用(为简洁起见,删除了错误处理):
请注意,进程 ID 可以回收 - 最好缓存从 CreateProcess 调用返回的句柄。
您还可以使用线程池 API 的 ( SetThreadpoolWait(Vista+ 上)、RegisterWaitForSingleObject(旧平台上))在进程退出时接收回调。
编辑:我错过了原始问题的“想要对流程做点什么”部分。如果可以在某些小窗口中使用可能过时的数据,或者如果您想在不尝试操作的情况下使操作失败,则可以使用此技术。您仍然需要处理由于进程已退出而导致操作失败的情况。
The process handle will be signaled if it exits.
So the following will work (error handling removed for brevity):
Note that process ID's can be recycled - it's better to cache the handle that is returned from the CreateProcess call.
You can also use the threadpool API's (SetThreadpoolWait on Vista+, RegisterWaitForSingleObject on older platforms) to receive a callback when the process exits.
EDIT: I missed the "want to do something to the process" part of the original question. You can use this technique if it is ok to have potentially stale data for some small window or if you want to fail an operation without even attempting it. You will still have to handle the case where the action fails because the process has exited.
正如评论中所述,@user152949 提供的解决方案会跳过第一个过程,并且在“存在”时不会中断" 设置为 true。让我提供一个固定版本:
The solution provided by @user152949, as it was noted in commentaries, skips the first process and doesn't break when "exists" is set to true. Let me provide a fixed version:
我今天发现这个,是2003年的。它通过名称找到一个进程,你甚至不需要pid。
I found this today, it is from 2003. It finds a process by name, you don't even need the pid.
监视子进程的另一种方法是创建一个工作线程,该线程将:
Another way of monitoring a child-process is to create a worker thread that will :
调用
EnumProcesses()
并检查 PID 是否在列表中。http://msdn.microsoft.com/en-我们/库/ms682629%28VS.85%29.aspx
call
EnumProcesses()
and check if the PID is in the list.http://msdn.microsoft.com/en-us/library/ms682629%28VS.85%29.aspx
您永远无法检查进程是否正在运行,只能检查进程是否在最近的某个时间正在运行。进程是不受应用程序控制的实体,可以随时退出。无法保证进程在检查进程是否正在运行和执行相应操作之间不会退出。
最好的方法是只执行所需的操作并捕获进程未运行时抛出的异常。
You can never check and see if a process is running, you can only check to see if a process was running at some point in the recent past. A process is an entity that is not controlled by your application and can exit at any moment in time. There is no way to guaranteed that a process will not exit in between the check to see if it's running and the corresponding action.
The best approach is to just do the action required and catch the exception that would be thrown if the process was not running.
JaredPar 是对的,你无法知道进程是否正在运行。您只能知道您检查时该进程是否正在运行。它可能已经死了。
您还必须意识到 PID 可以很快回收。因此,仅仅因为有一个带有您的 PID 的进程,并不意味着它就是您的进程。
让进程共享一个 GUID。 (进程 1 可以生成 GUID 并在命令行上将其传递给进程 2。)进程 2 应该使用该 GUID 创建一个命名互斥体。当进程 1 想要检查时,它可以在互斥锁上执行
WaitForSingleObject
,超时时间为 0。如果进程 2 消失,返回代码将告诉您互斥体已被放弃,否则您将超时。JaredPar is right in that you can't know if the process is running. You can only know if the process was running at the moment you checked. It might have died in the mean time.
You also have to be aware the PIDs can be recycled pretty quickly. So just because there's a process out there with your PID, it doesn't mean that it's your process.
Have the processes share a GUID. (Process 1 could generate the GUID and pass it to Process 2 on the command line.) Process 2 should create a named mutex with that GUID. When Process 1 wants to check, it can do a
WaitForSingleObject
on the mutex with a 0 timeout. If Process 2 is gone, the return code will tell you that the mutex was abandoned, otherwise you'll get a timeout.您可以通过简单地通过 CreateToolhelp32Snapshot,并使用 Process32First 和 Process32Next 调用该快照。
然后,您可以使用生成的 PROCESSENTRY32 结构的 th32ProcessID 字段或 szExeFile 字段,具体取决于您是要按 PID 还是可执行文件名称进行搜索。可以在此处找到一个简单的实现。
You may find if a process (given its name or PID) is running or not by iterating over the running processes simply by taking a snapshot of running processes via CreateToolhelp32Snapshot, and by using Process32First and Process32Next calls on that snapshot.
Then you may use th32ProcessID field or szExeFile field of the resulting PROCESSENTRY32 struct depending on whether you want to search by PID or executable name. A simple implementation can be found here.
在编写监控工具时,我采取了略有不同的方法。
仅仅为了使用 WaitForSingleObject 甚至 RegisterWaitForSingleObject (它会为你做这件事)而启动一个额外的线程感觉有点浪费。因为就我而言,我不需要知道进程关闭的确切时刻,只需知道它确实已关闭。
我使用 GetProcessTimes() 代替:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683223(v=vs.85).aspx
仅当满足以下条件时,GetProcessTimes() 才会返回进程 ExitTime 的 FILETIME 结构该进程实际上已退出。所以只需检查 ExitTime 结构是否已填充以及时间是否不为 0 即可;
此解决方案应该考虑进程已被终止但其 PID 被另一个进程重用的情况。 GetProcessTimes 需要进程的句柄,而不是 PID。因此操作系统应该知道该句柄是在某个时刻运行但不再运行的进程的句柄,并为您提供退出时间。
依赖 ExitCode 感觉很脏:/
While writing a monitoring tool, i took a slightly different approach.
It felt a bit wasteful to spin up an extra thread just to use WaitForSingleObject or even the RegisterWaitForSingleObject (which does that for you). Since in my case i don't need to know the exact instant a process has closed, just that it indeed HAS closed.
I'm using the GetProcessTimes() instead:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683223(v=vs.85).aspx
GetProcessTimes() will return a FILETIME struct for the process's ExitTime only if the process has actually exited. So is just a matter of checking if the ExitTime struct is populated and if the time isn't 0;
This solution SHOULD account the case where a process has been killed but it's PID was reused by another process. GetProcessTimes needs a handle to the process, not the PID. So the OS should know that the handle is to a process that was running at some point, but not any more, and give you the exit time.
Relying on the ExitCode felt dirty :/
这是我过去使用过的解决方案。尽管这里的示例是在 VB.net 中 - 我已经在 C 和 C++ 中使用了这种技术。它绕过了进程 ID 和进程 ID 的所有问题。处理句柄和返回代码。无论 Process2 如何终止,Windows 都会非常忠实地释放互斥体。我希望它对某人有帮助......
This is a solution that I've used in the past. Although the example here is in VB.net - I've used this technique with c and c++. It bypasses all the issues with Process IDs & Process handles, and return codes. Windows is very faithful in releasing the mutex no matter how Process2 is terminated. I hope it is helpful to someone...