前一篇文章介绍了如何获取 IShellDispatch 指针的多种方法。接下来我就用刚才拿到的 IShellDispatch 指针来获取指定文件夹下指定文件的右键菜单列表并执行。
有以下几个步骤:
- 通过 IShellDispatch::NameSpace() 拿到文件夹的 Shell 命名空间 Folder;
- 通过 Folder::ParseName() 拿到文件夹内某一文件对应的对象 FolderItem;
- 通过 FolderItem::Verbs() 拿到该文件的右键菜单动作列表 FolderItemVerbs;
- 调用 FolderItemVerbs::get_Count() 拿到动作列表内动作的个数;
- 遍历 FolderItemVerbs::Item() 拿到某一个单独的动作对象 FolderItemVerb;
拿到该动作对象后,就可以调用 FolderItemVerb::get_Name() 取得在菜单里面的名字,调用 FolderItemVerb::DoIt() 即可执行动作命令。
以下是部分示例源代码:(完整源代码:Source.cpp)
bool ListShellVerb(IShellDispatch* pShellDispatch, const wchar_t* dir, const wchar_t* file)
{
HRESULT hr;
CComVariant varFolder(dir);
CComPtr<Folder> spFolder;
// 拿到目录
hr = pShellDispatch->NameSpace(varFolder, &spFolder);
if (FAILED(hr) || !spFolder)
return false;
CComBSTR bstrFile(file);
CComPtr<FolderItem> spFolderItem;
// 拿到文件
hr = spFolder->ParseName(bstrFile, &spFolderItem);
if (FAILED(hr) || !spFolderItem)
return false;
CComPtr<FolderItemVerbs> spVerbs;
// 拿到动作列表
hr = spFolderItem->Verbs(&spVerbs);
if (FAILED(hr) || !spVerbs)
return false;
long nItems = 0;
spVerbs->get_Count(&nItems);
// 遍历并获取每个动作的名字
for (long i = 0; i < nItems; i++) {
CComBSTR bsName;
CComPtr<FolderItemVerb> spVerb;
hr = spVerbs->Item(CComVariant(i), &spVerb);
if (SUCCEEDED(hr) && spVerb) {
spVerb->get_Name(&bsName);
std::wcout << (const wchar_t*)bsName << std::endl;
// 执行动作命令
// spVerb->DoIt();
}
}
return true;
}
int main()
{
// 控制台支持 Unicode 输出
std::wcout.imbue(std::locale("chs"));
CoInitialize(nullptr);
// 版本1
CComPtr<IShellDispatch> spShellDispatch1 = GetShellDispatch_v1();
ListShellVerb(spShellDispatch1, LR"(C:\Windows\System32)", L"notepad.exe");
std::wcout << L"-----------------------------------------------------------\n";
// 版本2
CComPtr<IShellDispatch> spShellDispatch2 = GetShellDispatch_v2();
ListShellVerb(spShellDispatch2, LR"(C:\Windows\System32)", L"notepad.exe");
CoUninitialize();
return 0;
}
以下是示例输出结果(英文版 Win10 操作系统),有些有弹出子菜单的不知道为啥没显示出来,也并不是所有菜单项都显示出来了,不知道原因:
&Open Run as &administrator Open with Code Restore previous &versions Cu&t &Copy Create &shortcut &Delete Rena&me P&roperties ----------------------------------------------------------- &Open Run as &administrator Open with Code &Pin to Start Scan with Windows Defender... Pin to tas&kbar Restore previous &versions Cu&t &Copy Create &shortcut &Delete Rena&me P&roperties
可以看到,虽然都不完整,但前面的比后面的这个更少,少了“附加到开始菜单”、“附加到任务栏”等等。