zoukankan      html  css  js  c++  java
  • 等待进程结束

    (转自:http://woshiyouyouchen.blog.163.com/blog/static/103998942009112194240398/)

    你还再为怎么判断一个程序是否结束而苦恼吗?或许你在想可以用一个循环每隔几秒来判断一次这个进程是否结束,但是这样会有问题,如果间隔时间太短就会很占CPU资源,间隔时间太长又不能及时知道程序已经结束,或许有人马上就想到WaitForSingleObject函数,不错Win32 API提供的这个函数能很好的解决这个问题,但是在使用WaitForSingleObject函数的过程中很容易忽略一些问题。小弟不才,在这里略说一二。
       先看一下函数的原形
     DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
       参数hHandle是同步对象的句柄。
       参数dwMilliseconds是以毫秒为单位的超时间隔,如果该参数为0,那么函数就测试同步对象的状态并立即返回,如果该参数为INFINITE,则超时间隔是无限的。

    等待进程结束 - 悠悠 - 悠悠
     
            表12.1 WaitForSingleObject的返回值
     WaitForSingleObject函数能使线程阻塞其自身执行的等待函数。只有在作为其参数的同步对象产生信号时才会返回。或在超过规定的等待时间后,不管有无信号,函数也都会返回。在等待函数未返回时,线程处于等待状态,此时线程只消耗很少的CPU时间。
     1、等待自己创建的进程
     怎么使用WaitForSingleObject函数呢,假设我们现在启动系统的记事本程序,然后等待记事本结束,代码可以这样写:
      CString strCommand="";
      STARTUPINFO si = {sizeof(si)};
      PROCESS_INFORMATION pi;
      CHAR cWindowsDir[MAX_PATH];
      CHAR cCommand[MAX_PATH];
     
      GetWindowsDirectory(cWindowsDir,MAX_PATH);  //获取系统目录
      strCommand= (CString)cWindowsDir+"\\NotePad.exe";
      strcpy(cCommand,strCommand);  //得到记事本的程序路径
     
      BOOL bRet = CreateProcess(NULL,cCommand,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);//启动记事本程序
      if (bRet)
      {
       if (!WaitForSingleObject(pi.hProcess,INFINITE))// 等待记事本程序关闭
       {
        AfxMessageBox("记事本已经关闭!");
       }
      }
     
     2、等待已经存在的进程
     现在我们知道记事本什么时候关闭了,那么关闭的时候我们就可以做我们想做的事情。但是一般的程序都不是通过CreateProcess创建的,要获取已经在运行状态的程序怎么办呢?没错,要想办法得到运行程序的进程ID,这就要借助OpenProcess函数,OpenProcess函数用来打开一个已经存在的进程对象,原形如下:
     HANDLE OpenProcess ( DWORD dwDesiredAccess,
       BOOL bInheritHandle,
       DWORD dwProcessId
     )
     dwDesiredAccess参数,进程的操作权限。
     bInheritHandle 句柄是否继承
     dwProcessId进程ID
     返回值:如果调用成功,函数返回一个该进程的句柄,如果失败返回NULL。
     怎么获取进程ID呢,需要用到另外几个函数CreateToolHelp32Snapshot、Process32First、Process32Next,这几个函数都是在TLHELP32.H中,用来一起完成对系统进程的枚举(就像任务管理器把进程都枚举出来一样)
     HANDLE WINAPI CreateToolhelp32Snapshot(
       DWORD dwFlags,
       DWORD th32ProcessID
     );
     dwFlags参数是一个标志,一般使用TH32CS_SNAPPROCESS,
     th32ProcessID参数是进程ID,如果第一个参数是TH32CS_SNAPPROCESS,这个参数就会被忽略。
     返回值,如果调用成功,返回一个Snapshot的句柄,失败返回INVALID_HANDLE_VALUE;
     BOOL WINAPI Process32First(
       HANDLE hSnapshot,
       LPPROCESSENTRY32 lppe
     );
     hSnapshot参数需要赋值为通过CreateToolHelp32Snapshot的句柄
     lppe参数是进程的入口信息,需要定义一个PROCESSENTRY32类型的变量来获取这个值。
     Process32Next和 Process32First函数的参数意义一致,这三个函数一起就可以不断对进程进行枚举,直到Process32Next的返回值为FALSE。
     那么可以这样实现等待已经在运行的进程对象
     PROCESSENTRY32  pe32;
     HANDLE hSnaphot;
     HANDLE hApp;
     DWORD dProcess;
     
     hSnaphot = CreateToolHelp32Snaphot(TH32CS_SNAPPROCESS,0); //获取进程快照
     Process32First(hSnaphot, &pe32); //指向第一个进程
     do
     {
     if (lstrcmpi(pe32.szExeFile,_T("NotePad.exe"))==0) //查找进程名称为NotePad.exe(记事本的程序)
     {
     dProcess = pe32.th32ProcessID;
     break;
     }
     }while(Process32Next(hSnaphot, &pe32)); // 不断循环直到取不到进程
     
     hApp= OpenProcess(
    PROCESS_VM_OPERATION|SYNCHRONIZE,FALSE,dProcess);
    //根据进程ID获取程序的句柄
      if (!WaitForSingleObject(hApp,INFINITE))// 等待记事本程序关闭
      {
       AfxMessageBox("记事本已经关闭!");
    }
       到现在,我们不但知道了怎么使用WaitForSingleObject的等待函数,还知道了GetWindowsDirectory、CreateProcess、OpenProcess、CreateToolHelp32Snapshot、Process32First、Process32Next等函数的用法,这些函数一起实现了我们想要的功能,而且还在其他方面起着重要的作用
  • 相关阅读:
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》内容介绍
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》前言
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》内容介绍
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》微软中国.NET Micro Framework项目组工程师所作之序
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》资源汇总
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》微软中国.NET Micro Framework项目组工程师所作之序
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》前言
    Windows、Linux、ARM、Android、iOS全平台支持的RTMP推流组件libEasyRTMP库接口调用说明
    简单高效易用Windows/Linux/ARM/Android/iOS平台实现RTMP推送组件EasyRTMPAndroid MediaCodec硬编码流程介绍
    RTSP网络监控摄像头如何实现Windows、Linux、ARM、Android、iOS全平台支持的拉RTSP流推出RTMP直播流?
  • 原文地址:https://www.cnblogs.com/imlucky/p/3040809.html
Copyright © 2011-2022 走看看