不想用WaitForSingleObject()函数,怎么监控CreateProcess()调用的可执行文件运行是否结束?

nodefault 2007-03-26 10:52:14
我的程序如下:
  SetCurrentDirectory(strPath);
  BOOL fRet = CreateProcess(NULL,"Promo.exe",NULL,NULL,FALSE,
       NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
        NULL, NULL, &si, &pi);
  if(fRet)
  {
hProcess = pi.hProcess;
bDone=false; //正在运行
  }
  if( hProcess != 0)
  {
WaitForSingleObject(hProcess,INFINITE); //监控
CloseHandle(hProcess);
     bDone=true;//运行结束
  }
我的程序会停在WaitForSingleObject这里,一直等待"Promo.exe"执行完,不能做任何操作,提示"没有响应".可能是WaitForSingleObject太耗资源了!!!
  我想"Promo.exe"在执行时,我的VC程序能够并发地做其它事,并能很好的监控"Promo.exe"文件的执行情况.怎么办?是不是要变1个线程为多个线程?
  不想用WaitForSingleObject()函数,怎么监控CreateProcess()调用的可执行文件运行是否结束?
...全文
1324 点赞 收藏 10
写回复
10 条回复
Jazzlover 2007年03月28日
如何开线程等待:
1. 把你上面的代码放入一个线程函数中, 比如 void moniter_thread(void* p),
2. 在主线程中调用 _beginthread(或其他可以启动线程的函数)启动 moniter_thread,
3. 为了随时可以关闭程序,你调用
WaitForSingleObject(hProcess,INFINITE); 的时候,不用 INFINITE, 而用一个非0的时间,然后 放入一个控制的循环中,如下:
DWORD retval;
while( 1 != InterlockedExchange(&getout, 0) ){
retval = WaitForSingleObject(hProcess, 1000); //等待一秒钟
if(WAIT_TIMEOUT==retval)
continue;
else if(WAIT_OBJECT_0==retval){ //成功等待到信号
break;
}
}
那个 getout 是用来控制让这个线程退出的,你想退出时在 主线程里调用
InterlockedExchange((&getout, 1) 就可以了。
记住:在启动线程之前要调用 getout = 0, 不然线程一下就退出了。

控制线程的方法有很多种,比如靠信号量等,这种是我惯用的,你不一定要如此。

回复 点赞
wangk 2007年03月26日
开线程进行等待。
回复 点赞
nodefault 2007年03月26日
我的"Promo.exe"可执行文件没有源代码,估计用进程间通讯不行吧!
进程间通讯好像要在2个程序的源代码里设置握手协议的.
回复 点赞
clife 2007年03月26日
进程间通讯,或者写成服务器了,sock通讯也是可以的
回复 点赞
WingForce 2007年03月26日
WaitForSingleObject会进入阻塞状态等待信号或者超时,难道会占用"很少占用资源"吗? 程序执行到WaitForSingleObject时就象死机了一样.
========================================================================================

WaitForSingleObject当然不一定一个是"占用很少占用资源"的:

WaitForSingleObject方法是一个内核态线程同步方法,这个操作会进行用户态内核态的切换,windows将WaitForSingleObject所在的线程挂起而不会获得时间片。

相对使用一个while循环查看一个被互锁的全局变量,在需要同步的那个线程使用互锁函数操作该全局变量。这是一个典型的用户态同步方法,在while等待的时候,线程依然可以获得时间片,在时间片中进行while循环,检查标志变量。

所以,根据2种不同方法同步线程,根据不同的环境,会有不同的资源占用。如果等待时间比较长,很明显内核方法更好,因为它的开销是用户态内核态切换。如果等待时间比较短,可能就是用户态方法更好,因为有可能只需要进行1次时间片轮转即可。

如果需要实现lz的需求,简单的方法是创建一个新线程,去创建目标进程,并WaitForSingleObject来等待进程执行结束,然后向需要相应用户事件或者说需要继续执行的线程发送一条消息。

伪代码的例程大概是这样(这里假设是一个窗体程序):

#define msg_finished WM_USER+1

DWORD WINAPI run( LPVOID lpParameter )
{
  SetCurrentDirectory(strPath);
  BOOL fRet = CreateProcess(NULL,"Promo.exe",NULL,NULL,FALSE,
       NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
        NULL, NULL, &si, &pi);
  if(fRet)
  {
hProcess = pi.hProcess;
bDone=false; //正在运行
  }
  if( hProcess != 0)
  {
WaitForSingleObject(hProcess,INFINITE); //监控
PostMessage( *((HWND*)lpParameter), msg_finished, 0, 0);/* 发送消息 */
CloseHandle(hProcess);
     bDone=true;//运行结束
  }
}

//winmain

int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)

{

HWND hwnd;
DWORD dwThreadID;

//注册窗体之类的代码

ShowWindow (hwnd, nFunsterStil);

//启动目标进程,并等待结束
CreateThread( NULL, 0, &hwnd, 0, &dwThreadID );

//消息循环
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}

return messages.wParam;

}


//窗体消息处理器
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case msg_finished:
MessageBox( NULL, Finished", "Finished", MB_OK );
break;

case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;

default: /* for messages that we don't deal with */
return DefWindowProc (hWnd, message, wParam, lParam);
}

return 0;
}
回复 点赞
DentistryDoctor 2007年03月26日
用WaitForSingleObject是比较好的方法。


The GetExitCodeProcess function retrieves the termination status of the specified process.


BOOL GetExitCodeProcess(
HANDLE hProcess,
LPDWORD lpExitCode
);

Parameters
hProcess
[in] Handle to the process.
The handle must have the PROCESS_QUERY_INFORMATION access right. For more information, see Process Security and Access Rights.

lpExitCode
[out] Pointer to a variable to receive the process termination status.
Return Values
If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks
If the specified process has not terminated, the termination status returned is STILL_ACTIVE. If the process has terminated, the termination status returned may be one of the following:



The exit value specified in the ExitProcess or TerminateProcess function.
The return value from the main or WinMain function of the process.
The exception value for an unhandled exception that caused the process to terminate.

Warning If a process happens to return STILL_ACTIVE (259) as an error code, applications that test for this value could end up in an infinite loop.

回复 点赞
savior00 2007年03月26日
WaitForSingleObject 之前 应该有 SetEvent(),才继续执行的把
回复 点赞
nodefault 2007年03月26日
WaitForSingleObject会进入阻塞状态等待信号或者超时,难道会占用"很少占用资源"吗? 程序执行到WaitForSingleObject时就象死机了一样.

那位大虾能不能给我写几行"开线程去监视的代码?
回复 点赞
pshpan 2007年03月26日
jason176374(C--我把青春献给你) ( ) 信誉:100 Blog 2007-03-26 13:18:14 得分: 0

WaitForSingleObject肯定是会一直等到结束的. 而且很少占用资源.

如果要在等待的同时做操作, 那么只能开线程去监视.

====================================================================================

WaitForSingleObject会进入阻塞状态等待信号或者超时.而且LZ的意思好像是调用一个第三方程序,我觉得还是另开一线程去监视,方便的话再自定义消息,线程结束就通知主程序
回复 点赞
jason176374 2007年03月26日
WaitForSingleObject肯定是会一直等到结束的. 而且很少占用资源.

如果要在等待的同时做操作, 那么只能开线程去监视.
回复 点赞
发动态
发帖子
VC/MFC
创建于2007-09-28

7898

社区成员

42.1w+

社区内容

VC/MFC相关问题讨论
社区公告
暂无公告