C++程序中调用其他exe可执行文件方法

时间:2024-03-05 12:49:32

在编程过程中有个需求,点击某个按钮需要弹出系统的声音控制面板。在网上查了下代码中调用其他exe程序或者打开其他文件的方法。

自己借鉴网上的文章稍微总结下,加深下印象,也给方便自己用。

在代码中调用其他exe程序或者打开其他功能末班的方法主要有以下几种:

1.使用system函数

system函数,函数原型system(执行shell命令)定义函数是,int system(const char * string),可以调用一些DOS命令,比如:

system("cls");//清屏,等于在DOS上使用cls命令

例如:system("pause");//暂停当前的进程

system("dir"); //列出当前项目文件的目录

system函数会调用fork()函数产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回调用的进程,system函数不能控制程序窗口是否显示。一般在项目中,这种方法不予考虑。

2.使用execl或execv函数

这是exec函数族里面的两个函数,在UNIX环境下用的比较多,exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,也就是说在调用进程内部执行一个可执行文件,这里的可执行文件既可以是二进制文件,也可以是任何Linux下的可执行的脚本文件,与一般情况不同,exec函数族的函数执行成功后不会返回,只有调用失败了才会返回一个-1,从原程序的调用点接着往下执行。它也是不能控制程序窗口是否显示。

 

3.WinExec函数

WinExec函数可以方便地在应用程序中执行一个程序,执行一个标准程序一般使用:

WinExec(\'C:\WINDOWS\NOTEPAD.EXE\', SW_SHOWNORMAL);

第二个参数是控制程序主窗口的显示方式,用WinExec只能执行exe文件,但是WinExec函数不好控制主程序来等该exe程序的结束。WinExec是Windows的老函数了,现在的CreateProcess几乎可以替代WinExe的所有功能。

 

4.ShellExcecuteEx函数

这个函数主要是在文件上执行一个函数,如果执行成功则返回一个非0值,否则返回一个0值。函数的原型是:

WINSHELLAPI BOOL WINAPI ShellExecuteEx(
LPSHELLEXECUTEINFO lpExecInfo);

参数lpExecInfo:是数据结构 LPSHELLEXECUTEINFO 的地址,包含了和接收一些被执行的应用程序的一些信息。下面是一个使用的示例:

SHELLEXECUTEINFO ShExecInfo = {0}; 
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); 
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; 
ShExecInfo.hwnd = NULL; 
ShExecInfo.lpVerb = _T("open"); 
ShExecInfo.lpFile = _T("a.exe"); 
ShExecInfo.lpParameters = _T("-a a"); 
ShExecInfo.lpDirectory = NULL; 
ShExecInfo.nShow = SW_HIDE; 
ShExecInfo.hInstApp = NULL; 
ShellExecuteEx(&ShExecInfo);
AfxGetApp()->BeginWaitCursor();
WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
AfxGetApp()->EndWaitCursor();

这个函数可以通过ShExecInfo.lpParameters来传递exe文件的参数,通过属性ShExecInfo.nShow来控制程序窗口是否显示。

后面三个函数都是SDK函数,现在在执行项目中的exe文件的时候,使用比较多的就是后面得两个函数,我在自己的项目中使用的就是ShellExecuteEx函数,比CreateProcess函数使用方便一些。

 

5.使用CreateProcess函数

CreateProcess函数是新建一个进程,下面是一个使用CreateProcess函数的例子:

void createchildprocessandwaituntildone(const ansistring& strcmdline)
{

process_information piprocinfo;
startupinfo sistartinfo;

// set up members of startupinfo structure.
sistartinfo.cb = sizeof(startupinfo);
sistartinfo.lpreserved = null;
sistartinfo.lpreserved2 = null;
sistartinfo.cbreserved2 = 0;
sistartinfo.lpdesktop = null;
sistartinfo.dwflags = 0;


// create the child process.
createprocess(

null,
strcmdline.c_str(),
null, // process security attributes
null, // primary thread security attributes
0, // handles are inherited
0, // creation flags
null, // use parent\\'s environment
null, // use parent\\'s current directory
&sistartinfo, // startupinfo pointer
&piprocinfo); // receives process_information

// wait for the processs to finish
dword rc = waitforsingleobject(
piprocinfo.hprocess, // process handle
infinite);
}

使用CreateProcess函数,你必须人为地控制该进程的生死,这一方面是使用进程控制来实现。进程控制的意义在于可以创建一个进程,并且可以通过进程句柄结束进程。

 

 

VC中调用其他可执行程序,就我目前所知有三种方法:

  1. HINSTANCE ShellExecute(HWND hwnd,    LPCTSTRlpVerb,LPCTSTRlpFile,LPCTSTRlpParameters,LPCTSTRlpDirectory,INTnShowCmd);

    特殊需要讲的参数:
    lpVerb:对lpFile要执行的行为,包括"open","explore","print","edit","find","properties"
    lpFile:要操作的对象
    lpParameters:传递给为lpFile的参数
    nShowCmd:窗口的显示参数,不显示(SW_HIDE)
    注意:返回值如果小于32,则是错误,见具体错误

    其扩展函数ShellExecuteEx功能更全
    此函数声明包含在头文件shellapi.h,库是shell32.lib
  2. UINT WinExec(
                              LPCSTR
     lpCmdLine,  // command line
                               UINT uCmdShow           // window style
    );

    参数lpCmdLine为文件名+参数
    如果执行正确,返回值大于31

    声明在头文件windows.h,包含在kernel32.lib中
  3. BOOL CreateProcess(
          LPCTSTR
     lpApplicationName,                 // name of executable module
         LPTSTR
     lpCommandLine,                      // command line string
         LPSECURITY_ATTRIBUTES
     lpProcessAttributes, // SD
         LPSECURITY_ATTRIBUTES
     lpThreadAttributes,  // SD
          BOOL bInheritHandles,                      // handle inheritance option
         DWORD
     dwCreationFlags,                     // creation flags
         LPVOID
     lpEnvironment,                      // new environment block
          LPCTSTR lpCurrentDirectory,                // current directory name
         LPSTARTUPINFO
     lpStartupInfo,// startup information
          LPPROCESS_INFORMATION lpProcessInformation // process information
    );
    这个够复杂,启动一个进程的方式打开一个程序。声明所在的头文件和库同WinExec

以上三种方法,推荐使用第一种。第二种不推荐使用,因为它存在只是为了支持16位机的。


还需要考虑另外一个问题,就是后面程序的执行,可能需要等待这个进程结束之后才能执行,而不能两个进程并发执行。(两个进程一个是原进程,一个是启动的进程)。参考了:http://www.cnblogs.com/del/archive/2008/02/13/1067871.html

可以如下使用:

 

HANDLE hProg;
hProg=ShellExecute(NULL, "open", "xxx.exe", NULL, NULL, SW_HIDE);
WaitForSingleObject(hProg, INIFINTE);

 

在我使用的时候是要用一个MFC程序打开一个控制台程序,控制台程序执行结果写入到一个文档中,然后再用mfc程序读出。(为什么这么麻烦,是因为控制台程序用到的库是第三方库,不支持MFC,没办法)。

在控制台程序结束时,写的文件未必已经写完,并关闭了。所以还需要额外做些工作。

While(!FileExists(Result.TXT)) ;

READFile(Result.TXT);

注意while语句后面的";"

 

ShellExecute:

1.函数功能:
你可以给它任何文件的名字,它都能识别出来并打开它。
2.函数原型:
HINSTANCE ShellExecute(
HWND hwnd,
LPCTSTR lpOperation,
LPCTSTR lpFile,
LPCTSTR lpParameters,
LPCTSTR lpDirectory,
INT nShowCmd
); 
3.参数说明
hwnd:
用于指定父窗口句柄。当函数调用过程出现错误时,它将作为Windows消息窗口的父窗口。
lpOperation:
用于指定要进行的操作。
“open”操作表示执行由lpFile参数指定的程序,或打开由lpFile参数指定的文件或文件夹;
“print”操作表示打印由lpFile参数指定的文件;
“explore”操作表示浏览由lpFile参数指定的文件夹。
当参数设为NULL时,表示执行默认操作“open”。 
lpFile:
用于指定要打开的文件名、要执行的程序文件名或要浏览的文件夹名。
lpParameters:
若lpFile参数是一个可执行程序,则此参数指定命令行参数,否则此参数应为NULL.
lpDirectory:
用于指定默认目录.
nShowCmd:
若lpFile参数是一个可执行程序,则此参数指定程序窗口的初始显示方式,否则此参数应设置为0。
这个参数常用的常数:
SW_HIDE 隐藏窗口,活动状态给令一个窗口
SW_MINIMIZE 最小化窗口,活动状态给令一个窗口
SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOWMAXIMIZED 最大化窗口,并将其激活
SW_SHOWMINIMIZED 最小化窗口,并将其激活
SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口
SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口
SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口
SW_SHOWNORMAL 与SW_RESTORE相同
若ShellExecute函数调用成功,则返回值为被执行程序的实例句柄。若返回值小于32,则表示出现错误。 
4.使用方法:
例如:
ShellExecute(NULL,"open","iloveu.bmp",NULL,NULL,SW_SHOWNORMAL); 
用缺省的位图编辑器打开一个叫iloveu.bmp的位图文件,这个缺省的位图编辑器可能是 Microsoft Paint, Adobe Photoshop, 或者 Corel PhotoPaint。
这个函数能打开任何文件,甚至是桌面和URL快捷方式( .ink或 .url)。ShellExecute解析系统注册表HKEY_CLASSES_ROOT中所有的内容,判断启动那一个执行程序,并且启动一个新的实例或使用DDE将文件名连到一打开的实例。然后,ShellExecute 返回打开文件的应用的实例句柄。
ShellExecute(NULL, "open", "http://www.microsoft.com", NULL, NULL, SW_SHOWNORMAL); 
这个代码使你能访问微软的主页。当ShellExecute遇到文件名前面的“http:”时,可以判断出要打开的文件是Web文件,随之启动Internet Explorer 或者 Netscape Navigator 或者任何你使用的别的浏览器打开文件。
ShellExecute还能识别其它协议,象FTP、GOPHER。甚至识别“mailto”,如果文件名指向“mailto:zxn@hq.cninfo.net”,它启动电子邮件程序并打开一个待编辑的新邮件,例如:
ShellExecute(NULL, "open",“mailto:zxn@hq.cninfo.net”, NULL, NULL, SW_SHOWNORMAL);打开新邮件窗口。
总之,ShellExecute函数就是如此简单地打开磁盘文件和Internet文件。如果将第二个参数“OPEN”改为“PRINT”或者“EXPLORE”,ShellExecute将能打印文件和打开文件夹。ShellExecute还有一个扩展函数ShellExecuteEx,所带参数中有一个特殊的结构,功能更强,或者任何你使用的别的浏览器打开文件。

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

 

VC中调用其他可执行程序,就我目前所知有三种方法:

  1. HINSTANCE ShellExecute(HWND hwnd,    LPCTSTRlpVerb,LPCTSTRlpFile,LPCTSTRlpParameters,LPCTSTRlpDirectory,INTnShowCmd);

    特殊需要讲的参数:
    lpVerb:对lpFile要执行的行为,包括"open","explore","print","edit","find","properties"
    lpFile:要操作的对象
    lpParameters:传递给为lpFile的参数
    nShowCmd:窗口的显示参数,不显示(SW_HIDE)
    注意:返回值如果小于32,则是错误,见具体错误

    其扩展函数ShellExecuteEx功能更全
    此函数声明包含在头文件shellapi.h,库是shell32.lib
  2. UINT WinExec(
                              LPCSTR
     lpCmdLine,  // command line
                               UINT uCmdShow           // window style
    );

    参数lpCmdLine为文件名+参数
    如果执行正确,返回值大于31

    声明在头文件windows.h,包含在kernel32.lib中
  3. BOOL CreateProcess(
          LPCTSTR
     lpApplicationName,                 // name of executable module
         LPTSTR
     lpCommandLine,                      // command line string
         LPSECURITY_ATTRIBUTES
     lpProcessAttributes, // SD
         LPSECURITY_ATTRIBUTES
     lpThreadAttributes,  // SD
          BOOL bInheritHandles,                      // handle inheritance option
         DWORD
     dwCreationFlags,                     // creation flags
         LPVOID
     lpEnvironment,                      // new environment block
          LPCTSTR lpCurrentDirectory,                // current directory name
         LPSTARTUPINFO
     lpStartupInfo,// startup information
          LPPROCESS_INFORMATION lpProcessInformation // process information
    );
    这个够复杂,启动一个进程的方式打开一个程序。声明所在的头文件和库同WinExec

以上三种方法,推荐使用第一种。第二种不推荐使用,因为它存在只是为了支持16位机的。


还需要考虑另外一个问题,就是后面程序的执行,可能需要等待这个进程结束之后才能执行,而不能两个进程并发执行。(两个进程一个是原进程,一个是启动的进程)。参考了:http://www.cnblogs.com/del/archive/2008/02/13/1067871.html

可以如下使用:

 

HANDLE hProg;
hProg=ShellExecute(NULL, "open", "xxx.exe", NULL, NULL, SW_HIDE);
WaitForSingleObject(hProg, INIFINTE);

 

在我使用的时候是要用一个MFC程序打开一个控制台程序,控制台程序执行结果写入到一个文档中,然后再用mfc程序读出。(为什么这么麻烦,是因为控制台程序用到的库是第三方库,不支持MFC,没办法)。

在控制台程序结束时,写的文件未必已经写完,并关闭了。所以还需要额外做些工作。

While(!FileExists(Result.TXT)) ;

READFile(Result.TXT);

注意while语句后面的";"

 

ShellExecute:

1.函数功能:
你可以给它任何文件的名字,它都能识别出来并打开它。
2.函数原型:
HINSTANCE ShellExecute(
HWND hwnd,
LPCTSTR lpOperation,
LPCTSTR lpFile,
LPCTSTR lpParameters,
LPCTSTR lpDirectory,
INT nShowCmd
); 
3.参数说明
hwnd:
用于指定父窗口句柄。当函数调用过程出现错误时,它将作为Windows消息窗口的父窗口。
lpOperation:
用于指定要进行的操作。
“open”操作表示执行由lpFile参数指定的程序,或打开由lpFile参数指定的文件或文件夹;
“print”操作表示打印由lpFile参数指定的文件;
“explore”操作表示浏览由lpFile参数指定的文件夹。
当参数设为NULL时,表示执行默认操作“open”。 
lpFile:
用于指定要打开的文件名、要执行的程序文件名或要浏览的文件夹名。
lpParameters:
若lpFile参数是一个可执行程序,则此参数指定命令行参数,否则此参数应为NULL.
lpDirectory:
用于指定默认目录.
nShowCmd:
若lpFile参数是一个可执行程序,则此参数指定程序窗口的初始显示方式,否则此参数应设置为0。
这个参数常用的常数:
SW_HIDE 隐藏窗口,活动状态给令一个窗口
SW_MINIMIZE 最小化窗口,活动状态给令一个窗口
SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOWMAXIMIZED 最大化窗口,并将其激活
SW_SHOWMINIMIZED 最小化窗口,并将其激活
SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口
SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口
SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口
SW_SHOWNORMAL 与SW_RESTORE相同
若ShellExecute函数调用成功,则返回值为被执行程序的实例句柄。若返回值小于32,则表示出现错误。 
4.使用方法:
例如:
ShellExecute(NULL,"open","iloveu.bmp",NULL,NULL,SW_SHOWNORMAL); 
用缺省的位图编辑器打开一个叫iloveu.bmp的位图文件,这个缺省的位图编辑器可能是 Microsoft Paint, Adobe Photoshop, 或者 Corel PhotoPaint。
这个函数能打开任何文件,甚至是桌面和URL快捷方式( .ink或 .url)。ShellExecute解析系统注册表HKEY_CLASSES_ROOT中所有的内容,判断启动那一个执行程序,并且启动一个新的实例或使用DDE将文件名连到一打开的实例。然后,ShellExecute 返回打开文件的应用的实例句柄。
ShellExecute(NULL, "open", "http://www.microsoft.com", NULL, NULL, SW_SHOWNORMAL); 
这个代码使你能访问微软的主页。当ShellExecute遇到文件名前面的“http:”时,可以判断出要打开的文件是Web文件,随之启动Internet Explorer 或者 Netscape Navigator 或者任何你使用的别的浏览器打开文件。
ShellExecute还能识别其它协议,象FTP、GOPHER。甚至识别“mailto”,如果文件名指向“mailto:zxn@hq.cninfo.net”,它启动电子邮件程序并打开一个待编辑的新邮件,例如:
ShellExecute(NULL, "open",“mailto:zxn@hq.cninfo.net”, NULL, NULL, SW_SHOWNORMAL);打开新邮件窗口。
总之,ShellExecute函数就是如此简单地打开磁盘文件和Internet文件。如果将第二个参数“OPEN”改为“PRINT”或者“EXPLORE”,ShellExecute将能打印文件和打开文件夹。ShellExecute还有一个扩展函数ShellExecuteEx,所带参数中有一个特殊的结构,功能更强,或者任何你使用的别的浏览器打开文件。

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

 

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);