Невозможно зарегистрировать IExecuteCommand для контекстного меню.C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Невозможно зарегистрировать IExecuteCommand для контекстного меню.

Сообщение Anonymous »

Я пытаюсь зарегистрировать IExecuteCommand для контекстного меню текстового файла. Для этого я создал COM-сервер в DLL и зарегистрировал его в Windows. Для регистрации я использовал следующий REG-файл
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}"

В результате в контекстном меню текстовых файлов появляется пункт «Печать имен в отладчик», но при попытке выбрать это меню получаю следующее ошибка: «Класс не зарегистрирован» несмотря на то, что все необходимые инструкции по регистрации COM-компонента записаны в .reg-файле.
Тестирую в 64-разрядной версии Windows 10 (DLL также 64-разрядная версия) бит)
Как заставить работать меню «Печать имен в отладчик»? Код компонента COM можно увидеть ниже:

#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-файл

LIBRARY COMIExecuteCommand
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE


Подробнее здесь: https://stackoverflow.com/questions/793 ... ntext-menu
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»