使用 ShellExecuteEx 打开文件或执行程序

使用 ShellExecuteEx 打开文件或执行程序

可以使用 ShellExecuteEx 打开文件或执行程序,与 ShellExecute 比较,ShellExecuteEx 提供了更多的控制,但是看起来使用也更复杂。
原型

BOOL ShellExecuteEx(
  _Inout_ SHELLEXECUTEINFO *pExecInfo
);

输入输出参数都是 SHELLEXECUTEINFO 结构体。
SHELLEXECUTEINFO定义

typedef struct _SHELLEXECUTEINFO {
  DWORD     cbSize;//结构大小,sizeof(SHELLEXECUTEINFO)
  ULONG     fMask;//指定结构成员的有效性
  HWND      hwnd;//父窗口句柄或出错时显示错误父窗口的句柄,可以为 NULL
  LPCTSTR   lpVerb;//指定该函数的执行动作
  LPCTSTR   lpFile;//操作对象路径
  LPCTSTR   lpParameters;//执行参数,可以为 ULL
  LPCTSTR   lpDirectory;//工作目录,可以为 NULL
  int       nShow;//显示方式
  HINSTANCE hInstApp;//如果设置了 SEE_MASK_NOCLOSEPROCESS ,并且调用成功则该值大于32,调用失败者被设置错误值
  LPVOID    lpIDList;//ITEMIDLIST结构的地址,存储成员的特别标识符,当fMask不包括SEE_MASK_IDLIST或SEE_MASK_INVOKEIDLIST时该项被忽略
  LPCTSTR   lpClass;//指明文件类别的名字或GUID,当fMask不包括SEE_MASK_CLASSNAME时该项被忽略
  HKEY      hkeyClass;//获得已在系统注册的文件类型的Handle,当fMask不包括SEE_MASK_HOTKEY时该项被忽略
  DWORD     dwHotKey;//程序的热键关联,低位存储虚拟关键码(Key Code),高位存储修改标志位(HOTKEYF_),当fmask不包括SEE_MASK_HOTKEY时该项被忽略
  union {
    HANDLE hIcon;//取得对应文件类型的图标的Handle,当fMask不包括SEE_MASK_ICON时该项被忽略
    HANDLE hMonitor;//将文档显示在显示器上的Handle,当fMask不包括SEE_MASK_HMONITOR时该项被忽略
  } DUMMYUNIONNAME;
  HANDLE    hProcess;//指向新启动的程序的句柄。若fMask不设为SEE_MASK_NOCLOSEPROCESS则该项值为NULL。
                     //但若程序没有启动,即使fMask设为SEE_MASK_NOCLOSEPROCESS,该值也仍为NULL。
                     //如果没有新创建进程,也会为空
} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;

fMask 用于指定结构成员的内容和有效性,可为下列值的组合:

  • SEE_MASK_DEFAULT (0)默认
  • SEE_MASK_CLASSNAME 使用 lpClass 参数,如果 SEE_MASK_CLASSKEY 也有效,则用后者
  • SEE_MASK_CLASSKEY 使用 hkeyClass 参数
  • SEE_MASK_IDLIST 使用 lpIDList 参数
  • SEE_MASK_INVOKEIDLIST 使用选定项目的快捷菜单 IContextMenu 接口处理程序
  • SEE_MASK_ICON 使用 hIcon 给出的菜单,不能与 SEE_MASK_HMONITOR 共用,Vista之后
  • SEE_MASK_HOTKEY 使用 dwHotKey 参数
  • SEE_MASK_NOCLOSEPROCESS 如果执行之后需要返回进程句柄,或者等待执行完毕的话,则需要指定该参数,从结构参数意义可以看到 hProcess 和 hInstApp 都依赖该选项
  • SEE_MASK_CONNECTNETDRV 验证共享并连接到驱动器号
  • SEE_MASK_NOASYNC 不等待操作完成,直接返回,会创建一个后台线程运行。
  • SEE_MASK_FLAG_DDEWAIT 弃用,使用 SEE_MASK_NOASYNC
  • SEE_MASK_DOENVSUBST 环境变量会被展开
  • SEE_MASK_FLAG_NO_UI 出现错误,不显示错误消息框,比如不会弹出找不到文件之类的窗口,直接返回失败
  • SEE_MASK_UNICODE UNICODE 程序
  • SEE_MASK_NO_CONSOLE 继承父进程的控制台,而不是创建新的控制台,与 CREATE_NEW_CONSOLE 相反
  • SEE_MASK_ASYNCOK 执行在后台线程,调用立即返回
  • SEE_MASK_NOQUERYCLASSSTORE 弃用
  • SEE_MASK_HMONITOR 使用 hmonitor,不能与 SEE_MASK_ICON 共存
  • SEE_MASK_NOZONECHECKS 不执行区域检查
  • SEE_MASK_WAITFORINPUTIDLE 创建新进程后,等待进程变为空闲状态再返回,超时时间为1分钟
  • SEE_MASK_FLAG_LOG_USAGE 跟踪应用程序启动次数
  • SEE_MASK_FLAG_HINST_IS_SITE

lpVerb 参数与 ShellExecute 的 lpOperation 参数一致:

  • edit 用编辑器打开 lpFile 指定的文档,如果 lpFile 不是文档,则会失败
  • explore 浏览 lpFile 指定的文件夹
  • find 搜索 lpDirectory 指定的目录
  • open 打开 lpFile 文件,lpFile 可以是文件或文件夹
  • print 打印 lpFile,如果 lpFile 不是文档,则函数失败
  • properties 显示属性
  • runas 请求以管理员权限运行,比如以管理员权限运行某个exe
  • NULL 执行默认”open”动作

nShow 与 ShellExecute 的该参数一致:

  • SW_HIDE 隐藏窗口,活动状态给令一个窗口
  • SW_MINIMIZE 最小化窗口,活动状态给令一个窗口
  • SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态
  • SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态
  • SW_SHOWMAXIMIZED 最大化窗口,并将其激活
  • SW_SHOWMINIMIZED 最小化窗口,并将其激活
  • SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口
  • SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口
  • SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口
  • SW_SHOWNORMAL 与SW_RESTORE相同

如果设置了 SEE_MASK_NOCLOSEPROCESS ,调用成功则 hInstApp 返回大于32的值,调用失败会返回:

  • SE_ERR_FNF (2) 文件未找到
  • SE_ERR_PNF (3) 路径未找到
  • SE_ERR_ACCESSDENIED (5) 拒绝访问
  • SE_ERR_OOM (8) 内存不足
  • SE_ERR_DLLNOTFOUND (32) 动态库未找到
  • SE_ERR_SHARE (26) 无法共享打开的文件
  • SE_ERR_ASSOCINCOMPLETE (27) 文件关联信息不完整
  • SE_ERR_DDETIMEOUT (28) 操作超时
  • SE_ERR_DDEFAIL (29) 操作失败
  • SE_ERR_DDEBUSY (30) DDE 操作忙
  • SE_ERR_NOASSOC (31) 文件关联不可用

返回值
函数执行成功,返回 TRUE ,否则返回 FALSE ,可使用 GetLastError 获取错误码。

  • ERROR_FILE_NOT_FOUND 文件不存在
  • ERROR_PATH_NOT_FOUND 路径不存在
  • ERROR_DDE_FAIL DDE(动态数据交换)失败
  • ERROR_NO_ASSOCIATION 未找到与指定文件拓展名关联的应用
  • ERROR_ACCESS_DENIED 拒绝访问
  • ERROR_DLL_NOT_FOUND 未找到dll
  • ERROR_CANCELLED 功能提示用户提供额外信息,但是用户取消请求。
  • ERROR_NOT_ENOUGH_MEMORY 内存不足
  • ERROR_SHARING_VIOLATION 发生共享冲突

使用

    SHELLEXECUTEINFO sei;
    ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));//使用前最好清空
    sei.cbSize = sizeof(SHELLEXECUTEINFO);//管理员权限执行cmd,最基本的使用与 ShellExecute 类似
    sei.lpFile = _T("cmd.exe");
    sei.nShow = SW_SHOW;
    sei.lpVerb = _T("runas");
    ShellExecuteEx(&sei);

    ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
    sei.cbSize = sizeof(SHELLEXECUTEINFO);//打开 c:\\ 的属性
    sei.lpFile = _T("c:\\");
    sei.nShow = SW_SHOW;
    sei.fMask = SEE_MASK_INVOKEIDLIST;
    sei.lpVerb = _T("properties");
    ShellExecuteEx(&sei);

    ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
    sei.cbSize = sizeof(SHELLEXECUTEINFO);
    sei.lpFile = _T("c");//打开 c 的属性,正常情况下会提示文件路径不存在,
    sei.nShow = SW_SHOW;
    sei.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI;//使用 SEE_MASK_FLAG_NO_UI 使出错的情况下不提示错误
    sei.lpVerb = _T("properties");
    ShellExecuteEx(&sei);

    ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
    sei.cbSize = sizeof(SHELLEXECUTEINFO);
    sei.lpFile = _T("cmd.exe");
    sei.nShow = SW_SHOW;
    sei.fMask = SEE_MASK_NOCLOSEPROCESS;//使用 SEE_MASK_NOCLOSEPROCESS 参数
    sei.lpVerb = _T("open");
    if (ShellExecuteEx(&sei))//执行成功
    {
        if (sei.hProcess)//指定 SEE_MASK_NOCLOSEPROCESS 并其成功执行,则 hProcess 将会返回执行成功的进程句柄
            WaitForSingleObject(sei.hProcess, INFINITE);//等待执行完毕
    }
    else
    {
        CString s;
        s.Format(_T("ShellExecuteEx error,error code:%d"), GetLastError());
        MessageBox(s);
    }

其他诸如打开文件、打开网页等与 ShellExecute 类似。

你可能感兴趣的:(windows,API)