ShellExecute调用程序出现R6010 -abort() has been called 错误
HINSTANCE hIns = ShellExecute(NULL, "open", _T("../bin/xxxx.exe"), NULL, NULL, SW_SHOWNORMAL);
一个MFC工程,调用一个Win32工程的EXE,出现上述问题
EXE执行需要OpenCV等外部链接库,且链接库也位于EXE文件中,
需将依赖的链接库目录作为参数传入,即可正常执行
HINSTANCE hIns = ShellExecute(NULL, "open", _T("../bin/xxxx.exe"), NULL, _T("../bin/"), SW_SHOWNORMAL);
--------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
区别:
功能上: createprocess > shellexecute > winexec 复杂程度也是!
winexec() 只用于可执行文件,是一个老函数啦,虽然使用方便,但不推荐!(兼容性也不好)
shellexcute()是通过windows外壳打开任意文件,非可执行文件自动通过关联的程序打开对于可执行文件,区别不大,不过shellexcute可以指定运行时的工作路径
winexec() 必须有GetMessage或超时之后才返回!CreateProcess和ShellExecute都是直接返回的!
三个SDK函数( WinExec、ShellExec、CrateProcess )的语法:
WinExec
这个函数最简单,只有两个参数,原型如下:
UINT WinExec(
LPCSTR lpCmdLine, // 命令路径
UINT uCmdShow // 显示方式
;
两个参数,前一个指定路径,后一个指定显示方式如SW_SHOW,SW_MAXIMIZE,SW_HIDE等。
使用方法如下:
WinExec("Notepad.exe", SW_SHOW); // 打开记事本
WinExec("D:\\Program Files\\Test\\Test.exe",SW_SHOWMAXIMIZED); // 以最大化的方式打开Test.exe
需要注意的是若用 SW_SHOWMAXMIZED 方式去加载一个无最大化按钮的程序,譬如Neterm,Calc 等等,就不会出现正常的窗体,但是已经被加到任务列表里了。
ShellExecute
原型如下:
HINSTANCE ShellExecute(
HWND hwnd, //父窗口句柄
LPCTSTR lpOperation, //操作, 打开方式 "edit","explore","open","find","print","NULL"
LPCTSTR lpFile, //文件名,前面可加路径
LPCTSTR lpParameters, //参数
LPCTSTR lpDirectory, //默认文件夹
INT nShowCmd //显示方式
);
最后的那个参数,为窗口指定可视性方面的一个命令。
请用下述任何一个常数
SW_HIDE 隐藏窗口,活动状态给令一个窗口
SW_MINIMIZE 最小化窗口,活动状态给令一个窗口
SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOWMAXIMIZED 最大化窗口,并将其激活
SW_SHOWMINIMIZED 最小化窗口,并将其激活
SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口
SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口
SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口
SW_SHOWNORMAL 与SW_RESTORE相同
使用方法如下:
ShellExecute(NULL,"open","C:\\Test.txt",NULL,NULL,SW_SHOWNORMAL); // 打开C:\Test.txt 文件
ShellExecute(NULL, "open", "http://www.google.com",/ NULL, NULL, SW_SHOWNORMAL); // 打开网页www.google.com
ShellExecute(NULL,"explore", "D:\\C++",NULL,NULL,SW_SHOWNORMAL); // 打开目录D:\C++
ShellExecute(NULL,"print","C:\\Test.txt",NULL,NULL, SW_HIDE); // 打印文件C:\Test.txt
ShellExecute不支持定向输出。
ShellExecute不仅可以运行EXE文件,也可以运行已经关联的文件。
如果将FileName参数设置为“http:”协议格式,那么该函数将打开默认浏览器并链接到指定的URL地址。若用户机器中安装了多个浏览器,则该函数将根据Windows 9x/NT注册表中http协议处理程序(Protocols Handler)的设置确定启动哪个浏览器。
格式一:C++用法,唯一能开一个新窗口显示网页的方法
如:ShellExecuteA(NULL,NULL,"IEXPLORE.EXE",argv[1],NULL,SW_SHOWDEFAULT );
格式二:http://网站域名/网页文件名。
如:ShellExecute(handle, ‘open’, http:// ; www.neu.edu.cn/default.htm’,nil,nil, SW_SHOWNORMAL);
格式二:http://网站域名/网页文件名。
如:ShellExecute(handle, ‘open’, http:// ; www.neu.edu.cn’, nil, nil, SW_SHOWNORMAL);
如果将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:[email protected]’, nil, nil, SW_SHOWNORMAL);打开新邮件窗口,并自动填入收件人地址。若指定多个收件人地址,则收件人地址之间必须用分号或逗号分隔开(下同)。
格式三:mailto:用户账号@邮件服务器地址?subject=邮件主题&body=邮件正文
如:ShellExecute(handle, ‘open’, ‘ mailto:[email protected]?subject=Hello&Body=This is a test’, nil, nil, SW_SHOWNORMAL);打开新邮件窗口,并自动填入收件人地址、邮件主题和邮件正文。若邮件正文包括多行文本,则必须在每行文本之间加入换行转义字符%0a。
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 //用于在进程创建后接受相关信息
;
使用方法如下:
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:\\putty.exe",NULL,NULL,FALSE,NULL,NULL,NULL,NULL,&si,&pi);
可以看出,通过上面的几个不同的方法,都可以实现在应用程序中打开其他应用程序的目的,其中有些方法可能会麻烦一点,所以就需要我们根据不同的目的去选择最适合自己的方法去实现自己的目的!
关于三个SDK函数: WinExec, ShellExecute,CreateProcess 的其他注意事项:
1、定义头文件
在头文件stdafx.h中必须定义以下两个头文件:
#include <shlobj.h> // 可替换为 windows.h
#include <shellapi.h>
如果定义了头文件 #include <windows.h>的话就不必定义 #include <shlobj.h>了,"windows.h" 不光是包含了"shellapi.h",它还定义了许多数据类型,如果没有这些数据类型,shellapi.h本身会出错。
2、定义路径
C++中所表示的路径要用 " \\ "而不是平常所用的" \ ",所以以上三个函数表示路径都为:
Disk:\\Directory\\...\\File name
WinExec("D:\\Program Files\\Test\\Test.exe",SW_SHOWMAXIMIZED);
ShellExecute(NULL,"open","C:\\Test.txt",NULL,NULL,SW_SHOWNORMAL);
bool fRet=CreateProcess("D:\\putty.exe",NULL,NULL,FALSE,NULL,NULL,NULL,NULL,&si,&pi);
3、程序启动错误。例如我们需要启动程序A,而程序A需要调用dat、ini等数据及配置文件,此时只能使用ShellExecute,CreateProcess 并且一定要指定参数中的文件路径。
例如:ShellExecute(NULL,"open","D:\\Program Files\\推箱子\\BoxMan.exe",NULL,"D:\\Program Files\\推箱子\\",SW_SHOWNORMAL);
4、有时需要等待程序执行完成后进行其他操作,例如程序A,要载入数据文件,程序B要读取文件,此时程序B
只能等程序A执行完操作才能开启,由于不是一个进程,不能用多线程,不过理念是一样的就是调用WaitForSingleObject()。例程如下:
void Fun()
{
char szCommandLine[256]="D:\\Program Files\\推箱子\\BoxMan.exe";//执行文件路径
STARTUPINFO si={sizeof(si)}; //
PROCESS_INFORMATION pi; //
BOOL success;
success=::CreateProcess(NULL,szCommandLine,NULL,NULL, FALSE,0,NULL,"D:\\Program Files\\推箱子\\",&si,&pi);
if(success==FALSE)
AfxMessageBox("打开文件失败!");
else
{
AfxMessageBox("开启程序成功!");
HANDLE hProcess=pi.hProcess; //获得开启进出那个HANDLE
DWORD dw=::WaitForSingleObject(hProcess,INFINITE); //调用WaitForSingleObject等待事件
//如果notepad结束,将发出信号。
switch(dw) {
case WAIT_OBJECT_0:
AfxMessageBox("程序关闭");
break;
case WAIT_TIMEOUT:
AfxMessageBox("超时");
break;
case WAIT_FAILED:
AfxMessageBox("失败");
break;
}
}
}