ShellExecuteEx是什么?一篇文章带你快速了解它的作用!

吉云

今天跟大家唠唠我这几天折腾的`ShellExecuteEx`,一开始我看到这玩意儿也是一脸懵,不知道是干啥的,但是没办法,工作需要,硬着头皮上。

起因

ShellExecuteEx是什么?一篇文章带你快速了解它的作用!

起因是这样的,有个需求,需要在我们的程序里启动另一个程序,而且还要带参数,还得知道启动结果。最开始我想着直接`system()`函数一把梭,简单粗暴,但是后来发现不行,`system()`没法获取详细的启动信息,而且还阻塞主线程,体验太差。

探索

然后我就开始各种查资料,Google、Stack Overflow,各种搜,终于发现`ShellExecuteEx`这个东西。一看介绍,这玩意儿能满足我的需求,可以启动程序,可以传递参数,还能获取启动结果,简直是量身定做!

  • 我得包含头文件: #include <shellapi.h>
  • 然后,定义一个SHELLEXECUTEINFO结构体变量,这个结构体里包含所有需要的信息,比如要启动的程序路径,参数,工作目录等等。
  • 就要给这个结构体赋值,这里面坑还是挺多的。
    • cbSize:这个必须设置成sizeof(SHELLEXECUTEINFO),不然会出错。
    • fMask:这个很重要,决定你要获取哪些信息,我这里需要获取进程句柄,所以要设置SEE_MASK_NOCLOSEPROCESS
    • hwnd:这个是父窗口句柄,可以设置为NULL
    • lpVerb:这个是操作类型,比如"open""print"等等,我这里要启动程序,所以设置为NULL
    • lpFile:这个是要启动的程序路径。
    • lpParameters:这个是传递给程序的参数。
    • lpDirectory:这个是工作目录,可以设置为NULL
    • nShow:这个是窗口显示方式,比如SW_SHOWNORMALSW_HIDE等等,我这里要正常显示,所以设置为SW_SHOWNORMAL
  • 调用ShellExecuteEx(&sei)启动程序。

踩坑

看似简单,但是实际操作起来,各种问题。

  • COM 初始化:一开始我直接调用ShellExecuteEx,结果程序直接崩溃。后来查资料才知道,在使用ShellExecuteEx之前,需要先初始化COM库,调用CoInitialize(NULL)
  • 路径问题:程序路径一定要写对,最好用绝对路径,不然可能会找不到程序。
  • 参数问题:参数如果包含空格,需要用双引号括起来,不然可能会被分割成多个参数。
  • 权限问题:如果启动的程序需要管理员权限,需要设置* = "runas"

代码

cpp

#include

#include

#include

int main() {

SHELLEXECUTEINFO sei = {0};

* = sizeof(SHELLEXECUTEINFO);

* = SEE_MASK_NOCLOSEPROCESS;

* = NULL;

* = NULL; // 或者 "runas"

* = "C:\\Windows\\System32\\*"; // 绝对路径

* = "*"; // 参数

* = NULL;

* = SW_SHOWNORMAL;

CoInitialize(NULL); // 初始化COM

if (ShellExecuteEx(&sei)) {

std::cout << "程序启动成功!" << std::endl;

WaitForSingleObject(*, INFINITE); // 等待程序结束

DWORD exitCode;

GetExitCodeProcess(*, &exitCode);

std::cout << "程序退出码:" << exitCode << std::endl;

CloseHandle(*); // 关闭句柄

} else {

std::cerr << "程序启动失败!错误码:" << GetLastError() << std::endl;

CoUninitialize(); // 卸载COM

return 0;

总结

经过这几天的折腾,总算是把`ShellExecuteEx`搞明白。虽然过程有点痛苦,但是也学到很多东西。以后再遇到类似的需求,就不用抓瞎。`ShellExecuteEx`还是挺强大的,可以满足很多复杂的启动程序的需求。但是要注意一些细节问题,不然很容易出错。

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。

目录[+]