在程序运行过程中调用另一个程序

时间:2024-03-09 20:49:17

有3个函数可以使用:WinExec、ShellExecute、CreateProcess

1、WinExec

  这个函数最简单,只有两个参数,原型如下:

  UINT WinExec(
    LPCSTR lpCmdLine,
    UINT uCmdShow
  );

  lpCmdLine:指向一个空结束的字符串,串中包含将要执行的应用程序的命令行(文件名加上可选参数)。

  uCmdShow:定义Windows应用程序的窗口如何显示:SW_HIDE、SW_MINIMIZE、SW_RESTORE、SW_SHOW、SW_SHOWMAXIMIZED、SW_SHOWMINIMIZED、SW_SHOWMINNOACTIVE、SW_SHOWNA、SW_SHOWNOACTIVATE、SW_SHOWNORMAL;

  返回值:

  若函数调用成功,则返回值大于31。若函数调用失败,则返回值为下列之一:

  ① 0:系统内存或资源已耗尽。

  ② ERROR_BAD_FORMAT:EXE文件无效(非Win32.EXE或.EXE影像错误)。

  ③ ERROR_FILE_NOT_FOUND:指定的文件未找到。

  ④ ERROR_PATH_NOT_FOUND:指定的路径未找到。

  虽然Microsoft认为WinExec已过时,但是在许多时候,简单的WinExec函数仍是运行新程序的最好方式。简单地传送作为第一个参数的命令行,还需要决定如何显示程序(该程序也许会忽视它)的第二个参数。WinExec不允许用CreateProcess获得的所有选项,而它的确简单。

  使用方法如下:

  WinExec(_T("D:\\Program Files\\abc\\abc.exe"),SW_SHOWMAXIMIZED);

  WinExec("Notepad.exe", SW_SHOW);  // 打开记事本

  WinExec("D:/Program Files/01/01.exe",SW_SHOWMAXIMIZED);

  需要注意的是若用 SW_SHOWMAXMIZED 方式去加载一个无最大化按钮的程序,譬如Neterm,Calc 等等,就不会出现正常的 窗体,但是已经被加到任务列表里了。

2、ShellExecute

  ShellExecute比WinExex灵活一点,所以参数就要多一点,原型如下:

  HINSTANCE ShellExecute(

    HWND hwnd, //父窗口句柄

    LPCTSTR lpOperation,//打开方式

    LPCTSTR lpFile, //待打开的文件名,前面可加路径

    LPCTSTR lpParameters, //参数

    LPCTSTR lpDirectory, //默认文件路径

    INT nShowCmd //显示方式

   );

  hwnd:指向父窗口的窗口句柄。此窗口接收应用程序产生的任何信息框。

  lpOperation:此字符串指定要执行的操作:

    "open" 此函数打开由参数lpFile指定的文件,此文件可以是一个可执行文件或文档文件,也可是一个文件夹。

    "print" 此函数打印由参数lpFile指定的文件,此文件应是一个文档文件,假如此文件是一个可执行文件,则打开此文件。

    "explore" 此函数搜索由参数lpFile指定的文件夹,此文件应是一个文档文件,

    此参数可以为空。这种情况下,函数默认用于打开"open"由参数lpFile指定的文件。

  lpFile:指定要打开或打印的文件或者是要打开或搜索的文件夹。

  lpParameters:假如参数lpFile指定一个可执行文件,lpParameters指定要传递给应用程序的参数。假如lpFile指定一个文档文件,lpParameters应为空。

  lpDirectory:指定默认目录。

  nShowCmd:假如lpFile指定一个可执行文件,nShowCmd表明应用程序打开时如何显示。假如lpFile指定一个文档文件,nShowCmd应为空。

  返回值:

  若函数调用成功,则返回值大于32,否则为一个小于等于32的错误值。

  使用方法:

  ShellExecute(NULL,_T("open"),_T("abc.exe"),NULL,_T("D:\\Program Files\\abc\\"),SW_SHOWNORMAL);

  ShellExecute(NULL, \'\'open\'\', \'\'c:\\test\\readme.txt\'\', nll, nll, SW_SHOW);

  ShellExecute(NULL,"explore", "D:/C++",NULL,NULL,SW_SHOWNORMAL); // 打开目录D:/C++

  ShellExecute(NULL,"print","C:/Test.txt",NULL,NULL, SW_HIDE); // 打印文件C:/Test.txt

 

  ShellExecuteEx:这个windows函数用的不多,但是要手动提升进程的权限时,就要用这个函数。

  用法:

    SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)};  

    sei.lpVerb = TEXT("runas");   //“runas”表示使用管理员权限运行。

    sei.lpFile = TEXT("abc.exe"); 

    //sei.lpDirectory = TEXT("C:\\abc");

 

    sei.nShow = SW_SHOWNORMAL; 

    if (!ShellExecuteEx(&sei))  

    { 

      DWORD dwError = GetLastError(); 

      if(dwError==ERROR_CANCELLED) 

      { 

        printf("提升权限被用户拒绝\n"); 

      } 

      else if(dwError==ERROR_FILE_NOT_FOUND) 

      { 

        printf("所要执行的文件没有找到\n"); 

      }

    }

 

3、CreateProcess

  BOOL CreateProcess(

    LPCTSTR lpApplicationName, //执行程序名

    LPTSTR lpCommandLine, // 参数行

    //下面两个参数描述了所创建的进程和线程的安全属性,如果为NULL则使用默认的安全属性
    LPSECURITY_ATTRIBUTES lpProcessAttributes, // process security attributes
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // thread security attributes

    BOOL bInheritHandles, // 继承标志

    DWORD dwCreationFlags, // 创建标志

    LPVOID lpEnvironment, // 环境变量

    LPCTSTR lpCurrentDirectory, // 运行该进程的初始目录

    LPSTARTUPINFO lpStartupInfo, // 用于在创建子进程时设置各种属性

    LPPROCESS_INFORMATION lpProcessInformation //用于在进程创建后接受相关信息
  );

  lpApplicationName:指定了要执行的模块

  lpCommandLine:定义了要执行的命令行。

  lpProcessAttributes:指向一个SECURITY_ATTRIBUTES结构,该结构决定了返回的句柄是否可被子进程继承。

  lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构,该结构决定了返回的句柄是否可被子线程继承。

  bInheritHandles,:表明新进程是否从调用进程继承句柄。

  dwCreationFlags:定义控制优先类和进程创建的附加标志。

  lpEnvironment:指向一个新进程的环境块。

  lpCurrentDirectory:定义了子进程的当前驱动器和当前目录。

  lpStartupInfo:指向一个STARTUPINFO结构,该结构定义了新进程的主窗口将如何显示。

  lpProcessInformation:指向PROCESS_INFORMATION结构,该结构接受关于新进程的表示信息。

 

  在上面的参数中,使用了两个比较重要的数据结构:STARTUPINFO和PROCESS_INFORMATION。这两个结构的定义分别如下:

  typedef struct _STARTUPINFO {   // si
    DWORD cb; //结构长度
    LPTSTR lpReserved; //保留
    LPTSTR lpDesktop; //保留
    LPTSTR lpTitle; //如果为控制台进程则为显示的标题
    DWORD dwX; //窗口横坐标
    DWORD dwY; //窗口丛坐标
    DWORD dwXSize; //窗口宽度
    DWORD dwYSize; //窗口高度
    DWORD dwXCountChars; //控制台窗口字符号宽度
    DWORD dwYCountChars; //控制台窗口字符号高度
    DWORD dwFillAttribute; //控制台窗口填充模式
    DWORD dwFlags; //创建标记
    WORD wShowWindow; //窗口显示标记,如同ShowWindow中的标记

    WORD cbReserved2; //保留参数
    LPBYTE lpReserved2; //保留参数
    HANDLE hStdInput; //标准输入句柄
    HANDLE hStdOutput; //标准输出句柄
    HANDLE hStdError; //标准错误句柄
  } STARTUPINFO, *LPSTARTUPINFO;

  typedef struct _PROCESS_INFORMATION {    // pi
    HANDLE hProcess; //进程句柄
    HANDLE hThread; //进程的主线程句柄
    DWORD dwProcessId; //进程的ID
    DWORD dwThreadId; //进程的主线程ID
  } PROCESS_INFORMATION;

  

  在上述参数中,参数lpStartupInfo是STARTUPINFO结构。可以用来设置控制台的标题,新窗口的的初始大小和位置,及重定向标准输入和输出。参数lpProcessInformation返回进程和线程句柄,还包括进程和线程ID。这些句柄须拥有在参数lpProcessAttributes和lpThreadAttributes中规定的访问权。

 

  返回值:

  若函数调用成功,则返回值不为0;若函数调用失败,返回值为0。

  使用方法:

    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    memset(&si,0,sizeof(si));
    si.cb=sizeof(si);
    si.wShowWindow=SW_SHOW;
    si.dwFlags=STARTF_USESHOWWINDOW;

    bool fRet=CreateProcess("D:\\Program Files\\abc\\abc.exe",NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);