admin管理员组文章数量:1123224
I am trying to register IExecuteCommand for the context menu of a text file. To do this, I created a COM server in a DLL and registered it in Windows. For registration, I used the following .reg file
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\CLSID\{0DF1F277-A2CD-4202-86AA-4C0BF1B8C5E4}\InProcServer32]
@="C:\Users\Username\OneDrive\Desktop\COM\COMIExecuteCommand.dll"
"ThreadingModel"="Apartment"
[HKEY_CLASSES_ROOT\txtfile\shell\printnamestodebugger]
@="Print names to debugger"
[HKEY_CLASSES_ROOT\txtfile\shell\printnamestodebugger\command]
"DelegateExecute"="{0DF1F277-A2CD-4202-86AA-4C0BF1B8C5E4}"
As a result, the "Print names to debugger"
menu item appears in the context menu for text files, but when I try to select this menu, I get the following error: "Class not registered"
despite the fact that all the necessary instructions for registering the COM
component are written in the .reg file.
I am testing on Windows 10 64 bit (DLL also 64 bit)
How can I make the "Print names to debugger"
menu work? You can see the COM component code below:
#include "pch.h"
#include <windows.h>
#include <unknwn.h>
#include <new>
#include <shobjidl.h>
CLSID CLSID_ShellExtension = { 0xdf1f277, 0xa2cd, 0x4202, { 0x86, 0xaa, 0x4c, 0xb, 0xf1, 0xb8, 0xc5, 0xe4 } };// {0DF1F277-A2CD-4202-86AA-4C0BF1B8C5E4}
LONG g_cObjs;
void DllAddRef() { InterlockedIncrement(&g_cObjs); }
void DllRelease() { InterlockedDecrement(&g_cObjs); }
class CShellExtension
: public IExecuteCommand
, public IInitializeCommand
, public IObjectWithSelection
{
public:
CShellExtension();
// *** IUnknown ***
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// *** IInitializeCommand ***
STDMETHODIMP Initialize(PCWSTR pszCommandName, IPropertyBag* ppb);
// *** IObjectWithSelection ***
STDMETHODIMP SetSelection(IShellItemArray* psia);
STDMETHODIMP GetSelection(REFIID riid, void** ppv);
// *** IExecuteCommand ***
STDMETHODIMP SetKeyState(DWORD grfKeyState) { return S_OK; }
STDMETHODIMP SetParameters(LPCWSTR pszParameters) { return S_OK; }
STDMETHODIMP SetPosition(POINT pt) { return S_OK; }
STDMETHODIMP SetShowWindow(int nShow) { return S_OK; }
STDMETHODIMP SetNoShowUI(BOOL fNoShowUI) { return S_OK; }
STDMETHODIMP SetDirectory(LPCWSTR pszDirectory) { return S_OK; }
STDMETHODIMP Execute();
private:
~CShellExtension();
private:
LONG m_cRef;
IShellItemArray* m_psia;
};
CShellExtension::CShellExtension()
: m_cRef(1), m_psia(NULL)
{
DllAddRef();
}
CShellExtension::~CShellExtension()
{
if (m_psia) m_psia->Release();
DllRelease();
}
// guts of shell extension go in here eventually
class CFactory : public IClassFactory
{
public:
// *** IUnknown ***
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
STDMETHODIMP_(ULONG) AddRef() { return 2; }
STDMETHODIMP_(ULONG) Release() { return 1; }
// *** IClassFactory ***
STDMETHODIMP CreateInstance(IUnknown* punkOuter,
REFIID riid, void** ppv);
STDMETHODIMP LockServer(BOOL fLock);
};
CFactory c_Factory;
STDMETHODIMP CFactory::QueryInterface(REFIID riid, void** ppv)
{
IUnknown* punk = NULL;
if (riid == IID_IUnknown || riid == IID_IClassFactory) {
punk = static_cast<IClassFactory*>(this);
}
*ppv = punk;
if (punk) {
punk->AddRef();
return S_OK;
}
else {
return E_NOINTERFACE;
}
}
STDMETHODIMP CFactory::CreateInstance(
IUnknown* punkOuter, REFIID riid, void** ppv)
{
*ppv = NULL;
if (punkOuter) return CLASS_E_NOAGGREGATION;
CShellExtension* pse = new(std::nothrow) CShellExtension();
if (!pse) return E_OUTOFMEMORY;
HRESULT hr = pse->QueryInterface(riid, ppv);
pse->Release();
return hr;
}
STDMETHODIMP CFactory::LockServer(BOOL fLock)
{
if (fLock) DllAddRef();
else DllRelease();
return S_OK;
}
STDAPI DllGetClassObject(REFCLSID rclsid,
REFIID riid, void** ppv)
{
if (rclsid == CLSID_ShellExtension) {
return c_Factory.QueryInterface(riid, ppv);
}
*ppv = NULL;
return CLASS_E_CLASSNOTAVAILABLE;
}
STDAPI Test(REFCLSID rclsid,
REFIID riid, void** ppv)
{
return CLASS_E_CLASSNOTAVAILABLE;
}
STDAPI DllCanUnloadNow()
{
return g_cObjs ? S_OK : S_FALSE;
}
STDMETHODIMP CShellExtension::QueryInterface(
REFIID riid, void** ppv)
{
IUnknown* punk = NULL;
if (riid == IID_IUnknown || riid == IID_IExecuteCommand) {
punk = static_cast<IExecuteCommand*>(this);
}
else if (riid == IID_IInitializeCommand) {
punk = static_cast<IInitializeCommand*>(this);
}
else if (riid == IID_IObjectWithSelection) {
punk = static_cast<IObjectWithSelection*>(this);
}
*ppv = punk;
if (punk) {
punk->AddRef();
return S_OK;
}
else {
return E_NOINTERFACE;
}
}
STDMETHODIMP CShellExtension::SetSelection(IShellItemArray* psia)
{
if (psia) psia->AddRef();
if (m_psia) m_psia->Release();
m_psia = psia;
return S_OK;
}
STDMETHODIMP CShellExtension::GetSelection(
REFIID riid, void** ppv)
{
if (m_psia) return m_psia->QueryInterface(riid, ppv);
*ppv = NULL;
return E_NOINTERFACE;
}
STDMETHODIMP CShellExtension::Initialize(
PCWSTR pszCommandName,
IPropertyBag* ppb)
{
OutputDebugStringW(L"Command: ");
OutputDebugStringW(pszCommandName);
OutputDebugStringW(L"\r\n");
if (ppb) {
VARIANT vt;
VariantInit(&vt);
if (SUCCEEDED(ppb->Read(L"extra", &vt, NULL))) {
if (SUCCEEDED(VariantChangeType(&vt, &vt, 0, VT_BSTR))) {
OutputDebugStringW(L"extra: ");
OutputDebugStringW(vt.bstrVal);
OutputDebugStringW(L"\r\n");
}
VariantClear(&vt);
}
}
return S_OK;
}
STDMETHODIMP CShellExtension::Execute()
{
HRESULT hr;
if (m_psia) {
IEnumShellItems* pesi;
if (SUCCEEDED(hr = m_psia->EnumItems(&pesi))) {
IShellItem* psi;
while (pesi->Next(1, &psi, NULL) == S_OK) {
LPWSTR pszName;
if (SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH,
&pszName))) {
OutputDebugStringW(L"File: ");
OutputDebugStringW(pszName);
OutputDebugStringW(L"\r\n");
CoTaskMemFree(pszName);
}
psi->Release();
}
pesi->Release();
hr = S_OK;
}
}
else {
hr = E_UNEXPECTED;
}
return hr;
}
STDMETHODIMP_(ULONG) CShellExtension::AddRef()
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CShellExtension::Release()
{
ULONG cRef = --m_cRef;
if (cRef == 0) delete this;
return cRef;
}
HRESULT __stdcall DllRegisterServer()
{
return S_OK;
}
HRESULT __stdcall DllUnregisterServer()
{
return S_OK;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DEF file
LIBRARY COMIExecuteCommand
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
本文标签: cCannot register IExecuteCommand for context menuStack Overflow
版权声明:本文标题:c++ - Cannot register IExecuteCommand for context menu - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736556453a1944584.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论