Guest
IExecuteCommand kann nicht für das Kontextmenü registriert werden
Post
by Guest » 11 Jan 2025, 12:48
Ich versuche, IExecuteCommand für das Kontextmenü einer Textdatei zu registrieren. Dazu habe ich in einer DLL einen COM-Server erstellt und diesen in Windows registriert. Für die Registrierung habe ich die folgende .reg-Datei verwendet
Code: Select all
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}"
Als Ergebnis erscheint der Menüpunkt „Namen an Debugger drucken“ im Kontextmenü für Textdateien, aber wenn ich versuche, dieses Menü auszuwählen, erhalte ich Folgendes Fehler: „Klasse nicht registriert“, obwohl alle notwendigen Anweisungen zum Registrieren der COM-Komponente in der .reg-Datei geschrieben sind.
Ich teste unter Windows 10 64 Bit (DLL auch 64 bit)
Wie kann ich dafür sorgen, dass das Menü „Namen an Debugger drucken“ funktioniert? Sie können den COM-Komponentencode unten sehen:
Code: Select all
#include "pch.h"
#include
#include
#include
#include
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(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(this);
}
else if (riid == IID_IInitializeCommand) {
punk = static_cast(this);
}
else if (riid == IID_IObjectWithSelection) {
punk = static_cast(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-Datei
Code: Select all
LIBRARY COMIExecuteCommand
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
1736596081
Guest
Ich versuche, IExecuteCommand für das Kontextmenü einer Textdatei zu registrieren. Dazu habe ich in einer DLL einen COM-Server erstellt und diesen in Windows registriert. Für die Registrierung habe ich die folgende .reg-Datei verwendet [code]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}" [/code] Als Ergebnis erscheint der Menüpunkt „Namen an Debugger drucken“ im Kontextmenü für Textdateien, aber wenn ich versuche, dieses Menü auszuwählen, erhalte ich Folgendes Fehler: „Klasse nicht registriert“, obwohl alle notwendigen Anweisungen zum Registrieren der COM-Komponente in der .reg-Datei geschrieben sind. Ich teste unter Windows 10 64 Bit (DLL auch 64 bit) Wie kann ich dafür sorgen, dass das Menü „Namen an Debugger drucken“ funktioniert? Sie können den COM-Komponentencode unten sehen: [code]#include "pch.h" #include #include #include #include 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(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(this); } else if (riid == IID_IInitializeCommand) { punk = static_cast(this); } else if (riid == IID_IObjectWithSelection) { punk = static_cast(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; } [/code] DEF-Datei [code]LIBRARY COMIExecuteCommand EXPORTS DllGetClassObject PRIVATE DllCanUnloadNow PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE [/code]