SHELLEXECUTEINFO 和 ShellExecuteEx的使用

SHELLEXECUTEINFO 和 ShellExecuteEx的使用

在日常工作中用到的一些知识,很久没有总结过,前几日参加一个会议,很是无聊。自己思索着自己这两年来所做过的东西,写着写着居然也写下了 100 个知识点。想把它一条一条总结下来,动笔总不是很容易。就拿这篇文章作为第一篇。

       
很多东西取之于网络,也有一些自己的心得。才疏学浅,就当一个知识梳理的过程吧。
        
 
第一篇 SHELLEXECUTEINFO ShellExecuteEx 的使用

       
使用 SHELLEXECUTEINFO ShellExecuteEx ,我也主要是在 cab 包的安装时使用的。基本上是这样使用的,如下:

 

     SHELLEXECUTEINFO ShellInfo ;

             

     memset (&ShellInfo , 0, sizeof (ShellInfo ));

     ShellInfo .cbSize = sizeof (ShellInfo );

     ShellInfo .hwnd = NULL ;

     ShellInfo .lpVerb = _T ("open" );

     ShellInfo .lpFile = szFilePath ;

     ShellInfo .nShow = SW_SHOWNORMAL ;

     ShellInfo .fMask = SEE_MASK_NOCLOSEPROCESS ;

 

     BOOL bResult = ShellExecuteEx (&ShellInfo );

一、 SHELLEXECUTEINFO 结构

MSDN 中,它这样定义:

Contains information used by ShellExecuteEx

原型如下:

typedef struct _SHELLEXECUTEINFO {
       DWORD cbSize;  
       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

一个标志数组,用来设置其他成员的有效性。

hwnd

可选。执行 ShellExecuteEx 的窗口句柄,可设为 NULL

lpVerb

指定执行的动作,包括: edit explore find open print properties

lpFile

/0 结尾的字符串,指出 lpVerb 的操作对象的路径,被系统支持的操作包括文本的 open print

lpParameters

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

lpDirectory

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

nShow

必须。指定打开的程序的显示方式,为 SW_ 值中的一个。

hInstApp

out 】如果设置 SEE_MASK_NOCLOSEPROCESS S 值并且 ShellExecuteEx 调用成功,则该项的值大于 32 ,如果调用失败,则将设置为 SE_ERR_XXX 的错误值。

lpIDList

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

lpClass

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

hkeyClass

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

 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

指向新启动的程序的句柄。若 fMask 不设为 SEE_MASK_NOCLOSEPROCESS 则该项值为 NULL 。但若程序没有启动,即使 fMask 设为 SEE_MASK_NOCLOSEPROCESS ,该值也仍为 NULL

二、 ShellExecuteEx

功能 Performs an operation on a specified file 对指定应用程序执行某个操作

原型: 
 

BOOL ShellExecuteEx(LPSHELLEXECUTEINFO lpExecInfo
);

参数

lpExecInfo

[in, out]  一个指向 SHELLEXECUTEINFO 结构的指针,用来传递和保存应用程序执行相关的信息。

返回值

如果函数成功执行就返回 TRUE ,否则返回 FALSE 。可调用 GetLastError 获取错误信息。

备注

由于 ShellExecuteEx 能够将执行委托给那些由组件对象模型 COM 激活的 Shell 扩展(数据源,上下文菜单句柄,动词实现),因此在调用 ShellExecuteEx 之前要先初始化 COM 。某些 Shell 扩展要求单线程单元模型的 COM ,在这种情况下,应当像下面一般初始化 COM

CoInitializeEx (NULL,COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)

在某些情况下 ShellExecuteEx 并没有使用这种类型的 Shell 扩展,这时就无需初始化 COM 。虽然如此,总是在使用这个函数之前初始化 COM 是个不错的举措。

三、例子

1 、打开一个应用程序

     SHELLEXECUTEINFO ShellInfo ;

             

     memset (&ShellInfo , 0, sizeof (ShellInfo ));

     ShellInfo .cbSize = sizeof (ShellInfo );

     ShellInfo .hwnd = NULL ;

     ShellInfo .lpVerb = _T ("open" );

     ShellInfo .lpFile = szFilePath ; // 此处写执行文件的绝对路径

     ShellInfo .nShow = SW_SHOWNORMAL ;

     ShellInfo .fMask = SEE_MASK_NOCLOSEPROCESS ;

 

     BOOL bResult = ShellExecuteEx (&ShellInfo );

2 、如何打开一个文档

   程序代码如上

3 、如何打开一个网页

SHELLEXECUTEINFO ShellInfo ;

             

     memset (&ShellInfo , 0, sizeof (ShellInfo ));

     ShellInfo .cbSize = sizeof (ShellInfo );

     ShellInfo .hwnd = NULL ;

     ShellInfo .lpVerb = _T ("open" );

     ShellInfo .lpFile = _T ("http://www.sina.com" );

     ShellInfo .nShow = SW_SHOWNORMAL ;

     ShellInfo .fMask = SEE_MASK_NOCLOSEPROCESS ;

 

     BOOL bResult = ShellExecuteEx (&ShellInfo );

4 、如何启动一个程序,直到它运行结束?

SHELLEXECUTEINFO ShellInfo ;

             

     memset (&ShellInfo , 0, sizeof (ShellInfo ));

     ShellInfo .cbSize = sizeof (ShellInfo );

     ShellInfo .hwnd = NULL ;

     ShellInfo .lpVerb = _T ("open" );

     ShellInfo .lpFile = szFilePath ;

     ShellInfo .nShow = SW_SHOWNORMAL ;

     ShellInfo .fMask = SEE_MASK_NOCLOSEPROCESS ;

     ShellExecuteEx (&ShellInfo );

 

WaitForSingleObject(ShellInfo.hProcess,INFINITE);

四、参考文献

1 MSDN

http://msdn.microsoft.com/en-us/library/bb759784(VS.85).aspx

http://msdn.microsoft.com/en-us/library/bb762154(VS.85).aspx

2 SHELLEXECUTEINFO 结构

http://kaweh.candy.blog.163.com/blog/static/36818772200827352870/

SHELLEXECUTEINFO 结构

在C++中其结构为

typedef struct _SHELLEXECUTEINFO {
DWORD cbSize;
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;

 

在C#中其结构为

public struct SHELLEXECUTEINFO // 用于 ShellExecuteEx
{
public int cbSize;
public int fMask;
public int hwnd;
public string lpVerb;
public string lpFile;
public string lpParameters;
public string lpDirectory;
public int nShow;
public int hInstApp;
public int lpIDList;
public string lpClass;
public int hkeyClass;
public int dwHotKey;
public int hIcon;
public int hProcess;
}

 

参数详解:

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_idlist see_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


3 、说说 ShellExecuteEx

http://blog.csdn.net/kesalin/category/242901.aspx

 

ShellExecuteEx Function

对指定应用程序执行某个操作

语法:

BOOL ShellExecuteEx(      

    LPSHELLEXECUTEINFO lpExecInfo
); 

参数:

lpExecInfo

[in, out]  一个指向 SHELLEXECUTEINFO 结构的指针,用来传递和保存应用程序执行相关的信息。

返回值:

如果函数成功执行就返回 TRUE ,否则返回 FALSE 。可调用 GetLastError 获取错误信息。

备注:

由于 ShellExecuteEx 能够将执行委托给那些由组件对象模型 COM 激活的 Shell 扩展(数据源,上下文菜单句柄,动词实现),因此在调用 ShellExecuteEx 之前要先初始化 COM 。某些 Shell 扩展要求单线程单元模型的 COM ,在这种情况下,应当像下面一般初始化 COM

 

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) 

 

在某些情况下 ShellExecuteEx 并没有使用这种类型的 Shell 扩展 ,这时就无需初始化 COM 。虽然如此,总是在使用这个函数之前初始化 COM 是个不错的举措。

如果有多个显示器,并且你指定了一个 HWND 同时设置 lpExecInfo 的成员 lpVerb "Properties" ,那么由 ShellExecuteEx 创建的任何窗口都有可能显示在不正确的位置上。

如果这个函数执行成功,它会设置 SHELLEXECUTEINFO hInstApp 成员为一个大于 32 的值。如果函数执行失败, hInstApp 成员被设置为 SE_ERR_XXX (提示失败的原因)。虽然为了兼容 16 位的 windows 应用程序 hInstApp 被声明成一个句柄,但它并不是一个句柄。它只能被转型为整数,并同 32 SE_ERR_XXX 之类的错误代码比较。

提供 SE_ERR_XXX 之类的错误代码是为了兼容 ShellExecute 使用 GetLastError 可以获得更详细的错误信息。返回值可以使下列之一:

 

Error

Description

ERROR_FILE_NOT_FOUND

指定文件不存在

ERROR_PATH_NOT_FOUND

指定路径不存在

ERROR_DDE_FAIL

动态数据交换 (DDE) 处理失败

ERROR_NO_ASSOCIATION

没有与制定文件名扩展对应的应用程序

ERROR_ACCESS_DENIED

访问指定文件被拒绝

ERROR_DLL_NOT_FOUND

无法找到运行应用程序所必须的库文件

ERROR_CANCELLED

这个函数要求用户提供更多其他信息(译注:比如弹出对话框),但请求用户被取消了

ERROR_NOT_ENOUGH_MEMORY

没有足够的内存来执行操作

ERROR_SHARING_VIOLATION

共享违规发生了

Windows 95/98/Me : ShellExecuteEx Microsoft Layer for Unicode (MSLU) 所支持。为了使用这个函数,必须添加额外的文件到应用程序中去,请参考: Microsoft Layer for Unicode on Windows Me/98/95 Systems .

 

函数信息:

 

Minimum DLL Version

shell32.dll version 3.51 or later

Custom Implementation

No

Header

shellapi.h

Import library

shell32.lib

Minimum operating systems

Windows NT 4.0, Windows 95

Unicode

Implemented as ANSI and Unicode versions

 

 

 

下面举例说明如何使用这个函数, executePackage 这个函数用来执行某个应用程序。

  1. bool  executePackage( LPCWSTR  fileName,  LPCWSTR  args,  LPCWSTR  baseDir,  bool  wait)  
  2. {  
  3.     SHELLEXECUTEINFOW sei = { sizeof (SHELLEXECUTEINFOW) };  
  4.   
  5.     sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;  
  6.   
  7.     sei.lpFile = fileName;  
  8.     sei.lpParameters = args;  
  9.     sei.lpDirectory = baseDir;  
  10.   
  11.     if  (!ShellExecuteExW(&sei)) {  
  12.         return   false ;  
  13.     }  
  14.   
  15.     if  (wait) {  
  16.         HANDLE  hProcess = sei.hProcess;  
  17.         if  (hProcess != 0) {  
  18.             WaitForSingleObject(hProcess, INFINITE);  
  19.             CloseHandle(hProcess);  
  20.         }  
  21.     }  
  22.   
  23.     return   true ;  
  24. }  

 

你可能感兴趣的:(SHELLEXECUTEINFO 和 ShellExecuteEx的使用)