应用程序找到文件对象后,下一步通常是以某种方式处理它。 例如,应用程序可能想要启动另一个应用程序,以便用户修改数据文件。 如果感兴趣的文件是可执行文件,应用程序可能只想启动它。 本文档讨论如何使用 ShellExecute 或 ShellExecuteEx 来执行这些任务。
使用 ShellExecute 和 ShellExecuteEx
若要使用 ShellExecute 或 ShellExecuteEx,您的应用程序必须指定要操作的文件或文件夹对象,并提供一个verb 来指定要执行的操作。 对于 ShellExecute,请将这些值分配给相应的参数。 对于 ShellExecuteEx,请填写 SHELLEXECUTEINFO 结构的相应成员。 还有几个其他成员或参数可用于微调这两个函数的行为。
文件和文件夹对象可以是文件系统或虚拟对象的一部分,可以通过路径或指向项标识符列表(PIDL)的路径或指针来标识它们。
对象谓词
可用于对象的谓词实质上是你在对象的快捷菜单上找到的项。 若要查找可用的谓词,请查看注册表下面的
\HKEY_CLASSES_ROOTCLSID\{object_clsid}\Shell\verb
其中 object_clsid 是对象的类标识符(CLSID),并且 verb 是可用 verb的名称。 命令verb\子项包含数据,指示verb被调用时将会发生的情况。
若要找出哪些谓词可用于 预定义 Shell 对象,请查看注册表下面的
\ HKEY_CLASSES_ROOTobject_name\shell\verb
其中 object_name 是预定义 Shell 对象的名称。 同样,verb\命令 子项包含的数据指示了调用 verb 时会发生什么。
常用动词包括:
| Verb | DESCRIPTION |
|---|---|
| edit | 启动编辑器并打开文档进行编辑。 |
| find | 从指定目录开始启动搜索。 |
| open | 启动应用程序。 如果此文件不是可执行文件,则会启动其关联的应用程序。 |
| 打印文档 | |
| properties | 显示对象的属性。 |
| runas | 以管理员身份启动应用程序。 用户帐户控制(UAC)将提示用户同意运行提升的应用程序,或输入用于运行应用程序的管理员帐户的凭据。 |
每个 verb 命令对应于用于从控制台窗口启动应用程序的命令。 open verb这是一个很好的示例,因为它通常受支持。 对于 .exe 文件, open 只需启动应用程序。 但是,它更常用于启动对特定文件进行作的应用程序。 例如,Microsoft WordPad 可以打开 .txt 文件。 因此 openverb ,.txt 文件的对应内容类似于以下命令:
"C:\Program Files\Windows NT\Accessories\Wordpad.exe" "%1"
使用 ShellExecute 或 ShellExecuteEx 打开 .txt 文件时,Wordpad.exe 以指定文件作为其参数启动。 某些命令可以具有其他参数(例如标志),这些参数可以根据需要添加以正确启动应用程序。 有关快捷菜单和谓词的进一步讨论,请参阅 “扩展快捷菜单”。
一般情况下,尝试确定特定文件的可用谓词列表有点复杂。 在许多情况下,只需将 lpVerb 参数设置为 NULL,这将调用文件类型的默认命令。 此过程通常等效于将 lpVerb 设置为“”open,但某些文件类型可能具有不同的默认命令。 有关详细信息,请参阅 扩展快捷菜单 和 ShellExecuteEx 参考文档。
使用 ShellExecuteEx 从站点提供激活服务
站点链的服务可以控制项目激活过程的许多行为。 从 Windows 8 开始,可以提供一个站点链的指针给 ShellExecuteEx 以启用此类行为。 若要向 ShellExecuteEx 提供站点,请按以下步骤操作:
- 在 SHELLEXECUTEINFO 的 fMask 成员中指定SEE_MASK_FLAG_HINST_IS_SITE标志。
- 在 SHELLEXECUTEINFO 的 hInstApp 成员中提供 IUnknown。
使用 ShellExecute 启动搜索对话框
当用户在 Windows 资源管理器中右键单击文件夹图标时,菜单项之一是“搜索”。 如果他们选择该选项,则 Shell 启动其搜索工具。 此实用工具显示可用于搜索指定文本字符串的文件的对话框。 应用程序可以通过调用 ShellExecute(将“”find作为 lpVerb 参数)和目录路径作为 lpFile 参数以编程方式启动目录的搜索实用工具。 例如,以下代码行启动 c:\MyPrograms 目录的搜索实用工具。
ShellExecute(hwnd, "find", "c:\\MyPrograms", NULL, NULL, 0);
如何使用 ShellExecuteEx 的简单示例
以下示例控制台应用程序演示了 ShellExecuteEx 的使用。 为了清楚起见,省略了大多数错误检查代码。
#include <shlobj.h>
#include <shlwapi.h>
#include <objbase.h>
main()
{
LPITEMIDLIST pidlWinFiles = NULL;
LPITEMIDLIST pidlItems = NULL;
IShellFolder *psfWinFiles = NULL;
IShellFolder *psfDeskTop = NULL;
LPENUMIDLIST ppenum = NULL;
STRRET strDispName;
TCHAR pszParseName[MAX_PATH];
ULONG celtFetched;
SHELLEXECUTEINFO ShExecInfo;
HRESULT hr;
BOOL fBitmap = FALSE;
hr = SHGetFolderLocation(NULL, CSIDL_WINDOWS, NULL, NULL, &pidlWinFiles);
hr = SHGetDesktopFolder(&psfDeskTop);
hr = psfDeskTop->BindToObject(pidlWinFiles, NULL, IID_IShellFolder, (LPVOID *) &psfWinFiles);
hr = psfDeskTop->Release();
hr = psfWinFiles->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &ppenum);
while( hr = ppenum->Next(1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
{
psfWinFiles->GetDisplayNameOf(pidlItems, SHGDN_FORPARSING, &strDispName);
StrRetToBuf(&strDispName, pidlItems, pszParseName, MAX_PATH);
CoTaskMemFree(pidlItems);
if(StrCmpI(PathFindExtension(pszParseName), TEXT( ".bmp")) == 0)
{
fBitmap = TRUE;
break;
}
}
ppenum->Release();
if(fBitmap)
{
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = pszParseName;
ShExecInfo.lpParameters = NULL;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_MAXIMIZE;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
}
CoTaskMemFree(pidlWinFiles);
psfWinFiles->Release();
return 0;
}
应用程序首先检索 Windows 目录的 PIDL,并枚举其内容,直到找到第一个 .bmp 文件。 与前面的示例不同, IShellFolder::GetDisplayNameOf 用于检索文件的分析名称而不是显示名称。 由于这是一个文件系统文件夹,因此解析名称是一个完全限定的路径,这是 ShellExecuteEx 所需要的。
找到第一个 .bmp 文件后,会将相应的值分配给 SHELLEXECUTEINFO 结构的成员。 lpFile 成员被设置为文件的解析名称,lpVerb 成员被设置为 NULL,以开始默认操作。 在这种情况下,默认操作是“打开”。 然后,该结构将传递给 ShellExecuteEx,后者将启动位图文件的默认处理程序(通常 MSPaint.exe)到 open 该文件。 函数返回后,将释放 PIDL,并释放 Windows 文件夹的 IShellFolder 接口。