// C/C++ #include // Windows SDK #include // Windows Shell #include #include #include #include // ATL/COM #include IShellDispatch* GetShellDispatch_v1() { HRESULT hr; CComPtr spShellDisp; hr = CoCreateInstance(CLSID_Shell, nullptr, CLSCTX_INPROC, IID_IShellDispatch, (void**)&spShellDisp); return SUCCEEDED(hr) && spShellDisp ? spShellDisp.Detach() : nullptr; } IShellDispatch* GetShellDispatch_v2() { IShellDispatch* pShellDispatch = nullptr; CComPtr spShellWindows; if (SUCCEEDED(::CoCreateInstance(CLSID_ShellWindows, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&spShellWindows)))) { HWND hDesktop; CComPtr spDisp; CComVariant varEmpty; if (SUCCEEDED(spShellWindows->FindWindowSW(&varEmpty, &varEmpty, SWC_DESKTOP, (long*)&hDesktop, SWFO_NEEDDISPATCH, &spDisp))) { if (hDesktop != nullptr && hDesktop != INVALID_HANDLE_VALUE) { CComPtr spShellBrowser; if (SUCCEEDED(IUnknown_QueryService(spDisp, SID_STopLevelBrowser, IID_PPV_ARGS(&spShellBrowser)))) { CComPtr spShellView; if (SUCCEEDED(spShellBrowser->QueryActiveShellView(&spShellView))) { CComPtr spBackgroundDisp; if (SUCCEEDED(spShellView->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&spBackgroundDisp)))) { DWORD dwProcessId; if (::GetWindowThreadProcessId(hDesktop, &dwProcessId) && dwProcessId) { ::AllowSetForegroundWindow(dwProcessId); } if (CComQIPtr spShellFolderViewDual = spBackgroundDisp) { CComPtr spDisp; if (SUCCEEDED(spShellFolderViewDual->get_Application(&spDisp))) { if (CComQIPtr spShellDispatch = spDisp) { pShellDispatch = spShellDispatch.Detach(); } } } } } } } } } return pShellDispatch; } bool ListShellVerb(IShellDispatch* pShellDispatch, const wchar_t* dir, const wchar_t* file) { HRESULT hr; CComVariant varFolder(dir); CComPtr spFolder; // 拿到目录 hr = pShellDispatch->NameSpace(varFolder, &spFolder); if (FAILED(hr) || !spFolder) return false; CComBSTR bstrFile(file); CComPtr spFolderItem; // 拿到文件 hr = spFolder->ParseName(bstrFile, &spFolderItem); if (FAILED(hr) || !spFolderItem) return false; CComPtr 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 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() { // 控制台支持 Unicdoe 输出 std::wcout.imbue(std::locale("chs")); CoInitialize(nullptr); // 版本1 CComPtr spShellDispatch1 = GetShellDispatch_v1(); ListShellVerb(spShellDispatch1, LR"(C:\Windows\System32)", L"notepad.exe"); std::wcout << L"-----------------------------------------------------------\n"; // 版本2 CComPtr spShellDispatch2 = GetShellDispatch_v2(); ListShellVerb(spShellDispatch2, LR"(C:\Windows\System32)", L"notepad.exe"); CoUninitialize(); return 0; }