C++调用exe文件

来源:互联网 发布:tvp是什么软件 编辑:程序博客网 时间:2024/05/21 14:03

当项目比较大的时候,通常会分开来开发,如果分开的部分只是一些函数或类,整合的时候就可以使用静态库或动态库。但如果分开的是一个exe文件,整合的时候,就要通过调用exe文件来使用。尤其是当第三方软件是一个用c语言编写的exe文件时,更是需要如此。

最近在我所开发的LCDS系统当中就碰到了这样的问题。他需要调用一个分类器来处理数据,而手头上的分类器是经典的C4.5决策树分类器,它是用c语言写的,没有.h头文件,生成的是一个exe文件,通过在命令行执行main函数来处理数据。如果想把其改成静态库或动态库,因为没有头文件,改写后似乎不好调用其函数,因此考虑直接调用其生成的exe文件。可考虑的方法有:                                                      1.使用system函数
2.使用execl或execv函数
3.使用WinExec函数
4.使用CreateProcess函数
5.使用ShellExecuteEx函数
    system函数和execl、execv函数不能控制程序窗口是否显示,我要的效果是不显示该exe程序的窗口,所以这两种方法不予考虑。WinExec函数不好控制主程序来等该exe程序的结束,所以放弃。CreateProcess函数是新建一个进程,所以,你必须人为地控制该进程的生死,不如ShellExecuteEx方便,所以最终我选择的是ShellExecuteEx函数。程序如下:

SHELLEXECUTEINFO  ShExecInfo  {0}; 
 ShExecInfo.cbSize  sizeof(SHELLEXECUTEINFO); 
 ShExecInfo.fMask  SEE_MASK_NOCLOSEPROCESS; 
 ShExecInfo.hwnd  NULL; 
 ShExecInfo.lpVerb  _T("open"); 
 ShExecInfo.lpFile  _T("c4.5.exe");                         
 ShExecInfo.lpParameters  _T("-f train");             
 ShExecInfo.lpDirectory  NULL; 
 ShExecInfo.nShow  SW_HIDE; 
 ShExecInfo.hInstApp  NULL;             
 ShellExecuteEx(&ShExecInfo);
 WaitForSingleObject(ShExecInfo.hProcess,INFINITE);//这句很重要,一定要写,是等待这个.exe运行结束后再向下执行,特别是下面的代码依赖于.exe的运行结果时。

ShellExecuteEx 的参数在C++中其结构为:

typedef struct _SHELLEXECUTEINFO {
DWORD cbSize;   // typedef unsigned long DWORD;
ULONG fMask;
HWND hwnd;
LPCTSTR lpVerb;
LPCTSTR lpFile;
LPCTSTR lpParameters;
LPCTSTR lpDirectory;
int nShow;
HINSTANCE hInstApp;
LPVOID lpIDList;
LPCTSTR lpClass;
HKEY hkeyClass;
DWORD dwHotKey;
union {
HANDLE hIcon;
HANDLE hMonitor;
} DUMMYUNIONNAME;
HANDLE hProcess;

} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;

参数详解:

cbSize
存储该结构的长度,以字节为单位。

fMask
一个标志数组,用来设置其他成员的有效性
SEE_MASK_CLASSKEY          0x3
SEE_MASK_CLASSNAME          0x1
SEE_MASK_CONNECTNETDRV      0x80
SEE_MASK_DOENVSUBST          0x200
SEE_MASK_FLAG_DDEWAIT      0x100
SEE_MASK_FLAG_LOG_USAGE      0x4000000
SEE_MASK_FLAG_NO_UI          0x400
SEE_MASK_HMONITOR          0x200000
SEE_MASK_HOTKEY          0x20
SEE_MASK_ICON              0x10
SEE_MASK_IDLIST          0x4
SEE_MASK_INVOKEIDLIST      0xC
SEE_MASK_NOASYNC          0x100000
SEE_MASK_NOCLOSEPROCESS      0x40
SEE_MASK_NOZONECHECKS      0x800000
SEE_MASK_NO_CONSOLE          0x8000
SEE_MASK_UNICODE          0x100000
SEE_MASK_FILEANDURL          0x4000000


hwnd
调用这个ShellExecuteEx的窗口句柄

lpVerb
设定这个ShellExecuteEx的动作,包括:
    edit
    打开编辑器编辑文档,如果 lpFile 不是一个文档,则这个函数会失败
    explore
    以 lpFile 为路径打开资源管理器
    find
    从指定目录开始搜索
    open
    根据 lpFile 打开对应文件,该文件可以为可执行文件、文档或者文件夹
    print
    根据 lpFile 打印文档,若lpFile不是一个文档则该函数会失败 
    properties
    显示文件或文件夹的属性

lpFile
   以\0 结尾的字符串,指出 lpVerb 的操作对象的路径,被系统支持的操作包括文本的 open 、 print等,其中print要求必须有一个已经注册的打印机,而其他种类的文档会通过系统关联进行查询执行。若要设置一个空的namespace,则需要设置fMask的值为see_mask_invokeidlist。注意:若see_mask_invokeidlist已设置,则可以藉由lpFile或者lpIDList确定item的系统路径或者PIDL

lpParameters
运行/打开程序的参数,如果打开的是一个文档,则该项无效

lpDirectory
指明工作目录的名字,成员没有说明,则默认为当前目录

nShow
说明ShellExecuteEx打开的程序将以什么形式出现

hInstApp
如果函数运行成功,该项的值将大于32,否则会是下列错误对应的值

    SE_ERR_FNF 
    没有找到文件
    SE_ERR_PNF
    没有找到路径
    SE_ERR_ACCESSDENIED
    拒绝访问

    SE_ERR_OOM
    内存不足
    SE_ERR_DLLNOTFOUND
    没有找到动态链接库
    SE_ERR_SHARE
    不能操作一个以打开的文件
    SE_ERR_ASSOCINCOMPLETE
    文件关联信息不完整
    SE_ERR_DDETIMEOUT
    DDE操作超时
    SE_ERR_DDEFAIL
    DDE操作失败
    SE_ERR_DDEBUSY
    DDE繁忙
    SE_ERR_NOASSOC
    没有找到文件关联


lpIDList
一个itemidlist结构的地址,用来存储成员的特别标识符,当fMask不包括see_mask_idlistsee_mask_ invokeidlist 时该项被忽略

lpClass
用以指明文件类别的名字或GUID,当fMask不包括see_mask_classname时该项被忽略

hkeyClass
获得已在系统注册的文件类型的Handle,当fMask不包括see_mask_classkey时该项被忽略

dwHotKey
程序的热键关联,低位存储虚拟关键码(Key Code),高位存储修改标志位(HOTKEYF_),修改标志(modifier  flags)的详细列表请看wm_sethotkey消息的描述,当fmask不包括see_mask_hotkey时该项

被忽略

DUMMYUNIONNAME
hIcon
取得对应文件类型的图标的Handle,当fMask不包括SEE_MASK_ICON时该项被忽略

hMonitor
将文档显示在显示器上的Handle,当fMask不包括SEE_MASK_HMONITOR时该项被忽略

hProcess
用于进行return操作的成员,若fMask不设为see_mask_nocloseprocess则该项值为null,即使fMask设为

see_mask_nocloseprocess,若没有进程启动,该项值仍为null。即没有新的进程启动,则该项值一只为null


ShellExecuteEx的用法

    关于如何在c++中启动外部的exe程序,之前看到在百度一搜就看到了:

    ShellExecute(this->m_hWnd,"open","calc.exe","","", SW_SHOW );

    经验证果然可以,一条语句直接就启动了。之后我想在我的代码结束时也把这个exe程序给关闭了,按照网上的做法直接TerminateProcess(HINSTANCE,0)就不行了,参数根本就不能是HINSTANCE类型;然后使用send Message(WM_Close,...)也不行,原因应该是我的exe程序根本就没有窗口;最后使用了ShellExecuteEx,总算搞定了。

附上代码:

启动:

SHELLEXECUTEINFO ShExecInfo;

ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS ;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "xxx.exe"; //can be a file as well
ShExecInfo.lpParameters = "";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);

关闭:

if( ShExecInfo.hProcess != NULL)
{
      TerminateProcess(ShExecInfo.hProcess,0);
      ShExecInfo.hProcess = NULL;
}

原创粉丝点击