运行 Windows 程序并检测它何时以 C++ 结束

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1846385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:32:23  来源:igfitidea点击:

Running a Windows program and detect when it ends with C++

c++windowswinapiprocess

提问by EBAG

Suppose I run an application, after some time this app will get closed by user. Is it possible to find out when the program exits? Can I get it's process id when I run that application?

假设我运行一个应用程序,一段时间后该应用程序将被用户关闭。是否可以找出程序何时退出?当我运行该应用程序时,我可以获得它的进程 ID 吗?

回答by

This is a quote from here:

这是这里的引述:

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <conio.h>

void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
STARTUPINFO sj;
PROCESS_INFORMATION pj;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );

ZeroMemory( &sj, sizeof(sj) );
sj.cb = sizeof(sj);
ZeroMemory( &pj, sizeof(pj) );

// Start the child process p1.exe. Make sure p1.exe is in the
// same folder as current application. Otherwise write the full path in first argument.
if(!CreateProcess(L".\p1.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &sj, &pj))
{
printf( "Hello CreateProcess failed (%d)\n", GetLastError() );
getch();
return;
}

// Start child process p2.exe. Make sure p2.exe is in the
// same folder as current application. Otherwise write the full path in first argument.
if(!CreateProcess(L".\p2.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
printf( "CreateProcess2 failed (%d)\n", GetLastError() );
getch();
return;
}

// Wait until child processes exit.
WaitForSingleObject( pi.hProcess, INFINITE );
WaitForSingleObject( pj.hProcess, INFINITE );

// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
CloseHandle( pj.hProcess );
CloseHandle( pj.hThread );
getch();
}

回答by Bob Moore

CreateProcess and WaitForSingleObject is the simple way to achieve this: you get the process handle from CreateProcess, then wait for it with WFSO, not forgetting to close any handles you use. But wait... there's a problem. The problem is that - for GUI processes - both processes can hang. Why?

CreateProcess 和 WaitForSingleObject 是实现此目的的简单方法:您从 CreateProcess 获取进程句柄,然后使用 WFSO 等待它,不要忘记关闭您使用的任何句柄。但是等等……有问题。问题是 - 对于 GUI 进程 - 两个进程都可能挂起。为什么?

The problem arises because your application has a window but isn't pumping messages. If the spawned application invokes SendMessage with one of the broadcast targets (HWND_BROADCASTor HWND_TOPMOST), then the SendMessage won't return to the new application until all applications have handled the message - but your app can't handle the message because it isn't pumping messages.... so the new app locks up, so your wait never succeeds.... DEADLOCK.

出现问题是因为您的应用程序有一个窗口,但没有发送消息。如果生成的应用程序使用广播目标之一 (HWND_BROADCASTHWND_TOPMOST)调用 SendMessage ,则在所有应用程序都处理完消息之前,SendMessage 不会返回到新应用程序 - 但您的应用程序无法处理该消息,因为它没有泵送消息......所以新的应用程序锁定,所以你的等待永远不会成功......死锁。

If you have absolute control over the spawned application, then there are measures you can take, such as using SendMessageTimeout rather than SendMessage (e.g. for DDE initiations, if anybody is still using that). But there are situations which cause implicit SendMessage broadcasts over which you have no control, such as using the SetSysColors API for instance.

如果您对生成的应用程序拥有绝对控制权,那么您可以采取一些措施,例如使用 SendMessageTimeout 而不是 SendMessage(例如,对于 DDE 启动,如果有人仍在使用它)。但是在某些情况下会导致您无法控制的隐式 SendMessage 广播,例如使用 SetSysColors API。

The only safe ways round this are (a) split off the Wait into a separate thread, (b) use a timeout on the Wait and use PeekMessage in your Wait loop to ensure that you pump messages, (c) use the MsgWaitForMultipleObjects API instead of WaitForSingleObject.

解决此问题的唯一安全方法是 (a) 将 Wait 拆分为单独的线程,(b) 在 Wait 上使用超时并在 Wait 循环中使用 PeekMessage 以确保您泵送消息,(c) 改用 MsgWaitForMultipleObjects API的 WaitForSingleObject。

回答by rogerdpack

I would like to mention that you don't have to actually createa process, in order to be able to wait for its termination. Basically, if you know its PID, you can do this:

我想提一下,您不必实际创建一个进程,以便能够等待其终止。基本上,如果你知道它的 PID,你可以这样做:

 HANDLE h = OpenProcess(SYNCHRONIZE, TRUE, pid);
 WaitForSingleObject(h, INFINITE );

Full example: https://gist.github.com/rdp/6b5fc8993089ee12b44d(leave a comment here if you'd like a compiled version made available).

完整示例:https: //gist.github.com/rdp/6b5fc8993089ee12b44d(如果您希望提供编译版本,请在此处发表评论)。

回答by masterxilo

At least on Windows, there is some (underused?) C Runtime Library Functionality available for this. See Process and Environment Control">C Run-Time Library Reference > Process and Environment Control.

至少在 Windows 上,有一些(未充分利用?)C 运行时库功能可用于此。请参阅进程和环境控制">C 运行时库参考 > 过程和环境控制

Specifically, you have _spawnlp(_P_WAIT, cmdname, arg0, ..., argn, 0)("spawnwith argument list, using path variable to locate file") which searches cmdname in PATH and in the current directory. Note that "Following argn, there must be a NULL pointer to mark the end of the argument list."

具体而言,必须_spawnlp(_P_WAIT, cmdname, arg0, ..., argn, 0)(“产卵带有参数IST,使用pATH变量来查找文件”),该搜索在PATH和在当前目录cmdname。请注意“在 argn 之后,必须有一个 NULL 指针来标记参数列表的末尾。”

E.g.

例如

#include <stdio.h>
#include <process.h>
int main() {
    puts("waiting");
    _spawnlp(_P_WAIT, "mspaint.exe", "mspaint.exe", 0);
    puts("returned");
}

回答by Len Holgate

An alternative approach which offers even more control is to use the Win32 Job API, see CreateJobObject()and AssignProcessToJobObject(). This would allow you to monitor your spawned process asynchronously using an IO Completion Port using SetInformationJobObject()it's more complex and probably more than you need but it does give you much more control over the spawned processes.

提供更多控制的另一种方法是使用 Win32 作业 API,请参阅CreateJobObject()AssignProcessToJobObject()。这将允许您使用SetInformationJobObject()使用 IO 完成端口异步监视生成的进程,它更复杂,可能比您需要的更多,但它确实让您对生成的进程有更多的控制。

回答by alexkr

On Windows you can use WaitForSingleObjectto implement this functionality.

在 Windows 上,您可以使用WaitForSingleObject来实现此功能。

回答by Edison Gustavo Muenz

In a quick search at google I found these two methods from msdn which can be useful:

在谷歌的快速搜索中,我从 msdn 中找到了这两种有用的方法:

CreateProcessand GetExitCodeProcess. This assuming you are creating a process within your application.

CreateProcessGetExitCodeProcess。这假设您正在应用程序中创建一个进程。

You can do a polling method checking the created process status. I never did this kind of thing, but seems a very strange approach to me.

您可以使用轮询方法检查创建的进程状态。我从来没有做过这种事情,但对我来说似乎是一种很奇怪的做法。