启动应用程序(ShellExecute、ShellExecuteEx、SHELLEXECUTEINFO)

应用程序找到文件对象后,下一步通常是以某种方式处理它。 例如,应用程序可能想要启动另一个应用程序,以便用户修改数据文件。 如果感兴趣的文件是可执行文件,应用程序可能只想启动它。 本文档讨论如何使用 ShellExecuteShellExecuteEx 来执行这些任务。

使用 ShellExecute 和 ShellExecuteEx

若要使用 ShellExecuteShellExecuteEx,您的应用程序必须指定要操作的文件或文件夹对象,并提供一个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 启动应用程序。 如果此文件不是可执行文件,则会启动其关联的应用程序。
print 打印文档
properties 显示对象的属性。
runas 以管理员身份启动应用程序。 用户帐户控制(UAC)将提示用户同意运行提升的应用程序,或输入用于运行应用程序的管理员帐户的凭据。

每个 verb 命令对应于用于从控制台窗口启动应用程序的命令。 open verb这是一个很好的示例,因为它通常受支持。 对于 .exe 文件, open 只需启动应用程序。 但是,它更常用于启动对特定文件进行作的应用程序。 例如,Microsoft WordPad 可以打开 .txt 文件。 因此 openverb ,.txt 文件的对应内容类似于以下命令:

"C:\Program Files\Windows NT\Accessories\Wordpad.exe" "%1"

使用 ShellExecuteShellExecuteEx 打开 .txt 文件时,Wordpad.exe 以指定文件作为其参数启动。 某些命令可以具有其他参数(例如标志),这些参数可以根据需要添加以正确启动应用程序。 有关快捷菜单和谓词的进一步讨论,请参阅 “扩展快捷菜单”。

一般情况下,尝试确定特定文件的可用谓词列表有点复杂。 在许多情况下,只需将 lpVerb 参数设置为 NULL,这将调用文件类型的默认命令。 此过程通常等效于将 lpVerb 设置为“”open,但某些文件类型可能具有不同的默认命令。 有关详细信息,请参阅 扩展快捷菜单ShellExecuteEx 参考文档。

使用 ShellExecuteEx 从站点提供激活服务

站点链的服务可以控制项目激活过程的许多行为。 从 Windows 8 开始,可以提供一个站点链的指针给 ShellExecuteEx 以启用此类行为。 若要向 ShellExecuteEx 提供站点,请按以下步骤操作:

使用 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 接口。