有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。CreateProcess因为使用复杂,比较少用。

  WinExec主要运行EXE文件。
  ⑴ 函数原型: UINT Win Exec(LPCSTR lpCmdLine, UINT uCmdShow); 
  ⑵ 参数: 
  lpCmdLine:指向一个空结束的字符串,串中包含将要执行的应用程序的命令行(文件名加上可选参数)。 
  uCmdShow:定义Windows应用程序的窗口如何显示,并为CreateProcess函数提供STARTUPINFO参数的wShowWindow成员的值。 
  ⑶ 返回值: 
  若函数调用成功,则返回值大于31。若函数调用失败,则返回值为下列之一: 
  ① 0:系统内存或资源已耗尽。 
  ② ERROR_BAD_FORMAT:EXE文件无效(非Win32.EXE或.EXE影像错误)。 
  ③ ERROR_FILE_NOT_FOUND:指定的文件未找到。 
  ④ ERROR_PATH_NOT_FOUND:指定的路径未找到。 
  虽然Microsoft认为WinExec已过时,但是在许多时候,简单的WinExec函数仍是运行新程序的最好方式。简单地传送作为第一个参数的 命令行,还需要决定如何显示程序(该程序也许会忽视它)的第二个参数。通常,将其设置为SW_SHOW,也可尝试SW_MINIMIZED或 SW_MAXIMIZED。WinExec不允许用CreateProcess获得的所有选项,而它的确简单。

  ShellExecute不仅可以运行EXE文件,也可以运行已经关联的文件。 

1、标准用法
  ShellExecute函数原型及参数含义如下:

HINSTANCE ShellExecute(HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters,  LPCTSTR lpDirectory, INT nShowCmd);

  ●hWnd:用于指定父窗口句柄。当函数调用过程出现错误时,它将作为Windows消息窗口的父窗口。例如,可以将其设置为应用程序主窗口句柄,即Application.Handle,也可以将其设置为桌面窗口句柄(用GetDesktopWindow函数获得)。  
  ●lpOperation:用于指定要进行的操作。其中“open”操作表示执行由FileName参数指定的程序,或打开由FileName参数指定的文件或文件夹;“print”操作表示打印由FileName参数指定的文件;“explore”操作表示浏览由FileName参数指定的文件夹。当参数设为nil时,表示执行默认操作“open”。  
  ●lpFileName:用于指定要打开的文件名、要执行的程序文件名或要浏览的文件夹名。  
  ●lpParameters:若FileName参数是一个可执行程序,则此参数指定命令行参数,否则此参数应为nil或PChar(0)。  
  ●lpDirectory:用于指定默认目录。  
  ●lpShowCmd:若FileName参数是一个可执行程序,则此参数指定程序窗口的初始显示方式,否则此参数应设置为0。

  返回值:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <shellapi.h> int main( void )
{
HINSTANCE hNewExe = ShellExecuteA(NULL, "open", "d:\\tese.log", NULL, NULL, SW_SHOW);
if ((DWORD)hNewExe <= 32)
{
printf("return value:%d\n", (DWORD)hNewExe);
}
else
{
printf("successed!\n");
}
   printf("GetLastError: %d\n", GetLastError());
system("pause");
return 1;
}

  当“D:\\test.log”文件不存在是,执行结果如下:
  这里若函数执行错误, GetLastError()不一定能捕获到错误代码,例如当“d:\\tese.log”文件存在,将记事本"notepad.exe"命名为其他名字时:

  另外两个函数的返回值就不列出了。

2、特殊用法

  1)如果将FileName参数设置为“http:”协议格式,那么该函数将打开默认浏览器并链接到指定的URL地址。若用户机器中安装了多个浏览器,则该函数将根据Windows 9x/NT注册表中http协议处理程序(Protocols Handler)的设置确定启动哪个浏览器。  
  格式一:http://网站域名。        如:ShellExecute(handle, “open”, “http://www.neu.edu.cn”, nil, nil, SW_SHOWNORMAL);  
  格式二:http://网站域名/网页文件名。  如:ShellExecute(handle, “open”, “http://www.neu.edu.cn/default.htm”, nil, nil, SW_SHOWNORMAL);  
  2)如果将FileName参数设置为“mailto:”协议格式,那么该函数将启动默认邮件客户程序,如Microsoft Outlook(也包括Microsoft Outlook Express)或Netscape Messanger。若用户机器中安装了多个邮件客户程序,则该函数将根据Windows 9x/NT注册表中mailto协议处理程序的设置确定启动哪个邮件客户程序。  
  格式一:mailto:     如:ShellExecute(handle, "open", "mailto:", nil, nil, SW_SHOWNORMAL);打开新邮件窗口。  
  格式二:mailto:用户账号@邮件服务器地址  如:ShellExecute(handle, "open", "mailto:who@mail.neu.edu.cn", nil, nil, SW_SHOWNORMAL);
  打开新邮件窗口,并自动填入收件人地址。若指定多个收件人地址,则收件人地址之间必须用分号或逗号分隔开(下同)
如:ShellExecute(this->m_hWnd, "open", "mailto:nishinapp@yahoo.com", "", "", SW_SHOW);
  格式三:mailto:用户账号@邮件服务器地址?subject=邮件主题&body=邮件正文  
  如:ShellExecute(handle, "open", "mailto:who@mail.neu.edu.cn?subject=Hello&Body=This is a test", nil, nil, SW_SHOWNORMAL);
  打开新邮件窗口,并自动填入收件人地址、邮件主题和邮件正文。若邮件正文包括多行文本,则必须在每行文本之间加入换行转义字符%0a。

例子(delphi):  
在一个应用程序调用c:Project1.exe;  
  ShellExecute(handle, ’open’,’c:Project1.exe’,’字串内容’,nil, SW_SHOWNORMAL);  
在Project1.exe里可以调用:

procedure TForm1.FormCreate(Sender: TObject);  
var i:integer;
begin
for i:=1 to paramcount do
if ParamStr(i)〈〉’’ then showmessage(ParamStr(i));
end;

最后的那个参数,为窗口指定可视性方面的一个命令。 请用下述任何一个常数  
SW_HIDE 隐藏窗口,活动状态给令一个窗口  
SW_MINIMIZE 最小化窗口,活动状态给令一个窗口  
SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态  
SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态  
SW_SHOWMAXIMIZED 最大化窗口,并将其激活  
SW_SHOWMINIMIZED 最小化窗口,并将其激活  
SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口  
SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口  
SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口  
SW_SHOWNORMAL 与SW_RESTORE相同

  3、深入浅出ShellExecute  译者:徐景周(原作:Nishant       S)
      Q:  如何打开一个应用程序? 正如您所看到的,我并没有传递程序的完整路径。
  ShellExecute(this->m_hWnd, "open", "calc.exe", "", "", SW_SHOW);
      或ShellExecute(this->m_hWnd, "open", "notepad.exe", "c:\\MyLog.log", "", SW_SHOW);   
      Q:  如何打开一个同系统程序相关连的文档?
       ShellExecute(this->m_hWnd, "open", "c:\\abc.txt", "", "", SW_SHOW);   
      Q:  如何打开一个网页?
      ShellExecute(this->m_hWnd, "open", "http://www.google.com", "", "", SW_SHOW);   
      Q:  如何激活相关程序,发送EMAIL?
      ShellExecute(this->m_hWnd,"open", "mailto:nishinapp@yahoo.com","","",       SW_SHOW       );   
      Q:  如何用系统打印机打印文档?
      ShellExecute(this->m_hWnd, "print", "c:\\abc.txt", "", "", SW_HIDE);   
      Q:  如何用系统查找功能来查找指定文件?
      ShellExecute(m_hWnd, "find", "d:\\nish", NULL, NULL, SW_SHOW);   
      Q:  如何启动一个程序,直到它运行结束?

     SHELLEXECUTEINFO  ShExecInfo  =   {0};   
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "c:\\MyProgram.exe";
ShExecInfo.lpParameters = "";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess,INFINITE);

  或:

      PROCESS_INFORMATION  ProcessInfo;     
STARTUPINFO StartupInfo; //This is an [in] parameter
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo); //Only compulsory field
if(CreateProcess("c:\\winnt\\notepad.exe", NULL, NULL,NULL,FALSE,0,NULL, NULL,&StartupInfo,&ProcessInfo))
{
WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
}
else
{
MessageBox("The process could not be started...");
}

  Q: 如何显示文件或文件夹的属性?

      SHELLEXECUTEINFO  ShExecInfo   = {0};   
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_INVOKEIDLIST;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = "properties";
ShExecInfo.lpFile = "c:\\"; //can be a file as well
ShExecInfo.lpParameters = "";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);

使用CreateProcess命令 
  ⑴ 函数原型:

BOOL CreateProcess( 
 LPCTSTR lpApplicationName,
 LPTSTR lpCommandLine,
 LPSECURITY_ATTRIBUTES lpProcessAttributes,
 LPSECURITY_ATTRIBUTES lpThreadAttributes,
 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结构,该结构接受关于新进程的表示信息。 
  ⑶ 返回值: 
  若函数调用成功,则返回值不为0;若函数调用失败,返回值为0。

  在上述参数中,参数lpStartupInfo是STARTUPINFO结构。可以用来设置控台的标题,新窗口的的初始大小和位置,及重定向标准输入 和输出。新程序通常可以忽略多数这些数据项,如果选择那样做的话。可以规定该结构体中的标志,已表明要设置的数据段。有时,不想设置任何信息,也必须传递 一个有效的指针给空结构(确定设置大小到cb,及设置dwFlags成员为0)。参数lpProcessInformation返回进程和线程句柄,还包 括进程和线程ID。这些句柄拥有在参数lpProcessAttributes和lpThreadAttributes中规定的访问。 
  要注意,针对CreateProcess的一些参数对控制台应用程序是特定的,而其它参数则对各种应用程序有用。大多数情况下,并不一定要填入 STARTUPINFO结构,但无论如何必须提供它。其返回值是布尔型的,而真正感兴趣的返回值发生于作为参数传送的结构中 (PROCESS_INFORMATION)。CreateProcess返回该结构中的进程ID及其句柄,以及初始线程ID及其句柄。可以将ID发送到 其它进程,或使用句柄来控制新进程。

  ShellExecute和WinExec命令用于简单的作业。如果要完全控制一个新进程,就必须调用CreateProcess。 
【参考资料 感谢作者】
1、WinExec、ShellExecute和CreateProcess 
2、WINEXEC, SHELLEXECUTE, CREATEPROCESS

shellexecute返回的并不是目标程序的main返回值,这样做:
STARTUPINFO si={sizeof(si)};
PROCESS_INFORMATION pi;
si.dwFlags=STARTF_USESHOWWINDOW;//指定wShowWindow成员有效
si.wShowWindow=TRUE;//此成员设为TRUE的话则显示新建进程的主窗口
BOOL bRet=CreateProcess(
L"xx:\\xx.exe",//目标文件名
NULL,
NULL,//默认进程安全性
NULL,//默认进程安全性
FALSE,//指定当前进程内句柄不可以被子进程继承
CREATE_NEW_CONSOLE,//为新进程创建一个新的控制台窗口
NULL,//使用本进程的环境变量
NULL,//使用本进程的驱动器和目录
&si,
&pi);
if (bRet)
{
DWORD dwExitCode;
CloseHandle(pi.hThread);
DWORD dwResult=WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &dwExitCode);
CloseHandle(pi.hProcess);
printf("%d\n",dwResult);
printf("%d\n",dwExitCode);
}

以上代码是执行目标exe,等待其退出,得到main函数的返回值,用的是CreateProcess
需要#include <Windows.h>

C++运行外部exe并判断exe返回值的更多相关文章

  1. Visual Studio 2013 Ultimate & IIS Express 8.0 错误 [iisexpress.exe”已退出,返回值为 -1073741816 (0xc0000008)] 解决方法

    1. 开发环境 Visual Studio 2013 Ultimate IIS 8.0 Express 2. 错误信息 错误提示:iisexpress.exe”已退出,返回值为 -1073741816 ...

  2. ADO.NET笔记——使用Command执行增删改操作,通过判断ExecuteNonQuery()返回值检查是否操作成功

    相关知识: ExecuteNonQuery()方法:执行CommandText属性所制定的操作,返回受影响的记录条数.该方法一般用来执行SQL中的UPDATE.INSERT和DELETE等操作 对于U ...

  3. JAVA 和 C# 调用外部.exe文件,传值并等等exe完成,获取返回值

    JAVA- String ykexe = getProperty("ykexe") + " " + tableout; //getproperty(" ...

  4. VS2019开启调试,测试图片上传的时候,一点到图片上传,直接导致VS调试崩掉,返回 程序“[14764] iisexpress.exe”已退出,返回值为 -1 (0xffffffff)。 是什么原因导致的?

    试着使用管理员身份运行vs 今天调试的时候遇到个奇葩问题 一点上传控件选择文件后 就终止调试 发现根源不在上传控件 而是本地的中文输入法!关掉vs自动终止调试设置就好了 工具->选项-> ...

  5. LiteQuery MAX(Integer)、MAX(String) 判断是否返回值

    unit Unit6; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  6. C++ 需要返回值的函数却没有返回值的情况 单例模式

    昨天在看前些天写的代码,发现一个错误. #include <iostream> using namespace std; class singleton { public: static ...

  7. 无返回值的异步方法能否不用await

    1.无返回值的异步方法能否不用await? 如果你不需要等待加一的操作完成,那就可以直接执行后面的操作.那要看你的需求了,如果你后面的操作必须在加一的操作后执行,那就要await了 2.请问C#中如何 ...

  8. python asyncio 获取协程返回值和使用callback

    1. 获取协程返回值,实质就是future中的task import asyncioimport timeasync def get_html(url): print("start get ...

  9. IDEA生成带参数和返回值注释

    步骤说明 打开IDEA进入点击左上角 - 文件 - 设置 - 编辑器 - 活动模板 新建活动模板 填写模板文本 编辑变量 添加变量表达式 设置模板使用范围-设置全部范围应用-或者设置只在Java代码中 ...

随机推荐

  1. codeforces 689B B. Mike and Shortcuts(bfs)

    题目链接: B. Mike and Shortcuts time limit per test 3 seconds memory limit per test 256 megabytes input ...

  2. 从0开始学习Hadoop(2) 环境准备-Win7主机与Ubuntu虚拟机共享文件夹设置

    主机要跟虚拟机共享文件夹设置有很多种办法,这里提供一种本地用户的方式 1. 新增一个本地用户,密码等其他设置如下 2.选择文件目录,这是共享属性 Ubuntu端设置: 文件夹->连接到网络-&g ...

  3. QT笔记-布局

    1 QT中使用布局器QLayout布局 2自动计算各个空间的大小和位置 采用的既定policy策略来调整子窗口的大小和位置 3QHBoxLayout横向布局  QVBoxLayout纵向布局 QHBo ...

  4. winform 自动升级

    自动升级系统OAUS的设计与实现(续) (附最新源码) http://www.cnblogs.com/zhuweisky/p/4209058.html Winform在线更新 http://www.c ...

  5. WinHTTrack

    看过<大湿教我写.net通用权限框架(1)之菜单导航篇>之后发生的事 http://www.cnblogs.com/wolf-sun/p/3436585.html 用此工具下载别人整站的图 ...

  6. tools:context=".MainActivity的作用 (转载)

    转自:http://blog.csdn.net/caiwenfeng_for_23/article/details/8373569 <TextView android:layout_width= ...

  7. python 面向对象五 获取对象信息 type isinstance getattr setattr hasattr

    一.type()函数 判断基本数据类型可以直接写int,str等: >>> class Animal(object): ... pass ... >>> type( ...

  8. bzoj 1025: [SCOI2009]游戏【数学+dp】

    很容易发现行数就是lcm环长,也就是要求和为n的若干数lcm的个数 有结论若p1^a1+p2^a2+...+pm^am<=n,则ans=p1^a1p2^a2..*pm^am是n的一个可行答案.( ...

  9. JS 数据类型入门与typeof操作符

    标准的数据类型划分: 基本类型: number(数字).string(字符串).undefined.boolean(布尔值).null(空对象) //空对象与非空对象,最大的区别就是不能进行属性操作 ...

  10. 《Windows核心编程系列》八谈谈用内核对象进行线程同步

    使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...