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

发布于 2024-08-14 07:33:27 字数 75 浏览 1 评论 0 原文

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

幽蝶幻影 2024-08-21 07:33:27

这是此处的引用:

#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();
}

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();
}
奢望 2024-08-21 07:33:27

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

具体来说,您有 _spawnlp(_P_WAIT, cmdname, arg0, ..., argn, 0) (“带有参数 list 的 spawn,使用 path 变量来定位文件”)它在 PATH 和当前目录中搜索 cmdname。
请注意,“在 argn 之后,必须有一个 NULL 指针来标记参数列表的末尾。”

例如

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

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

Specifically, you have _spawnlp(_P_WAIT, cmdname, arg0, ..., argn, 0) ("spawn with 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."

E.g.

#include <stdio.h>
#include <process.h>
int main() {
    puts("waiting");
    _spawnlp(_P_WAIT, "mspaint.exe", "mspaint.exe", 0);
    puts("returned");
}
忘年祭陌 2024-08-21 07:33:27

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

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

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

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

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?

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_BROADCAST or 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.

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.

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.

清醇 2024-08-21 07:33:27

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

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

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

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

 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).

行雁书 2024-08-21 07:33:27

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

On Windows you can use WaitForSingleObject to implement this functionality.

带刺的爱情 2024-08-21 07:33:27

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

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.

清旖 2024-08-21 07:33:27

在 google 的快速搜索中,我从 msdn 中发现了这两种有用的方法:

CreateProcessGetExitCodeProcess< /a>.假设您正在应用程序中创建一个流程。

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文