Windows COM:DllGetClassObject未为DataHandler外壳扩展调用

Windows COM:DllGetClassObject未为DataHandler外壳扩展调用,windows,shell,datahandler,Windows,Shell,Datahandler,我正在尝试编写一个数据处理程序外壳扩展。在Windows Dev Center上,它表示“当对dragShell对象执行拖放操作时,将调用数据处理程序。它使您能够向拖放目标提供其他剪贴板格式。”我正在尝试在复制或拖动选定的文件目录后立即获取该文件目录 我可以看到GUID已在注册表中注册,并且在注册表中调用了DllMain和DllRegisterServer。但是DllGetClassObject从未被任何进程调用过。我希望在复制或拖动文件时,explorer.exe会调用它 我非常确定我是在x6

我正在尝试编写一个数据处理程序外壳扩展。在Windows Dev Center上,它表示“当对dragShell对象执行拖放操作时,将调用数据处理程序。它使您能够向拖放目标提供其他剪贴板格式。”我正在尝试在复制或拖动选定的文件目录后立即获取该文件目录

我可以看到GUID已在注册表中注册,并且在注册表中调用了DllMain和DllRegisterServer。但是DllGetClassObject从未被任何进程调用过。我希望在复制或拖动文件时,explorer.exe会调用它

我非常确定我是在x64配置下编译dll的,因为我的操作系统是Windows7 64位。CLSID是在VS 2010中使用“创建GUID”工具创建的。在注册之后,我可以看到CLSID位于shellex下DataHandler的子项下。dll的完整目录也在该CLSID注册表入口点中。所以我想不出它为什么不加载我的dll

尽管我可以找到一些关于shell扩展的文章,但大多数都是关于其他处理程序的。唯一相关的是以下链接:

我错在哪里?任何帮助都将不胜感激

这是DllMain中的代码

// {A097432A-44BE-44FC-AF1D-A012B65392F5}
static const GUID CLSID_DragObjectInfoExt = 
{ 0xA097432A, 0x44BE, 0x44FC, { 0xAF, 0x1D, 0xA0, 0x12, 0xB6, 0x53, 0x92, 0xF5 } };

HINSTANCE   g_hInst     = NULL;
long        g_cDllRef   = 0;


BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
    MessageBox(NULL, L"DllMain", L"QueryDragObject", MB_OK);
    switch (dwReason)
    {
    case DLL_PROCESS_ATTACH:
        g_hInst = hModule;
        DisableThreadLibraryCalls(hModule);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{
    MessageBox(NULL, L"DllGetClassObject", L"QueryDragObject", MB_OK);
    HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;

    if (IsEqualCLSID(CLSID_DragObjectInfoExt, rclsid))
    {
        hr = E_OUTOFMEMORY;

        ClassFactory *pClassFactory = new ClassFactory();
        if (pClassFactory)
        {
            hr = pClassFactory->QueryInterface(riid, ppv);
            pClassFactory->Release();
        }
    }

    return hr;
}

STDAPI DllCanUnloadNow(void)
{
    MessageBox(NULL, L"DllCanUnloadNow", L"QueryDragObject", MB_OK);
    return g_cDllRef > 0 ? S_FALSE : S_OK;
}

STDAPI DllRegisterServer(void)
{
/*  while(true) {
        Sleep(100);
    }*/
    MessageBox(NULL, L"DllRegisterServer", L"QueryDragObject", MB_OK);

    HRESULT hr;

    wchar_t szModule[MAX_PATH];
    if (GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule)) == 0)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        return hr;
    }

    // Register the component.
    hr = RegisterInprocServer(szModule, CLSID_DragObjectInfoExt, 
        L"TxtShellExtDragObjectHandler.DragObjectInfoExt Class", // Friendly name
        L"Apartment"); // Threading model
    if (SUCCEEDED(hr))
    {
        hr = RegisterShellExtDragInfoHandler(L"*", 
            CLSID_DragObjectInfoExt, 
            L"TxtShellExtDragObjectHandler.DragObjectInfoExt");
    }
    else
    {
        MessageBox(NULL, L"DllRegisterServer failed", L"DragObjectInfoHandler", MB_OK);
    }

    return hr;
}

STDAPI DllUnregisterServer(void)
{
    MessageBox(NULL, L"DllUnregisterServer", L"QueryDragObject", MB_OK);
    HRESULT hr = S_OK;

    wchar_t szModule[MAX_PATH];
    if (GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule)) == 0)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        return hr;
    }

    // Unregister the component.
    hr = UnregisterInprocServer(CLSID_DragObjectInfoExt);
    if (SUCCEEDED(hr))
    {
        // Unregister the context menu handler.
        hr = UnregisterShellExtDragInfoHandler(L"*", 
            CLSID_DragObjectInfoExt);
    }
    else
    {
        MessageBox(NULL, L"DllUnregisterServer failed", L"DragObjectInfoHandler", MB_OK);
    }

    return hr;
}

终于找出我做错的地方了

我在ContextMenu示例中使用了reg.h/cpp文件,只修改了几个地方。事实上,ContextMenuHandler和DataHandler的注册表树结构略有不同。正确的结构应如下所示:

HKEY_CLASSES_ROOT
   .fileType
      (Default) = MyProgram.1
   CLSID
      {00000000-1111-2222-3333-444444444444}
         InProcServer32
            (Default) = C:\MyDir\MyCommand.dll
            ThreadingModel = Apartment
   MyProgram.1
      (Default) = MyProgram Application
      Shellex
         DataHandler
            (Default) = {00000000-1111-2222-3333-444444444444}
在这之前,它就像:

HKEY_CLASSES_ROOT
   .fileType
      (Default) = MyProgram.1
   CLSID
      {00000000-1111-2222-3333-444444444444}
         InProcServer32
            (Default) = C:\MyDir\MyCommand.dll
            ThreadingModel = Apartment
   MyProgram.1
      (Default) = MyProgram Application
      Shellex
         DataHandler
            {00000000-1111-2222-3333-444444444444} = 
            'Friendly Name'

希望这篇文章能防止其他人犯同样的错误。

最终找出我做错的地方

我在ContextMenu示例中使用了reg.h/cpp文件,只修改了几个地方。事实上,ContextMenuHandler和DataHandler的注册表树结构略有不同。正确的结构应如下所示:

HKEY_CLASSES_ROOT
   .fileType
      (Default) = MyProgram.1
   CLSID
      {00000000-1111-2222-3333-444444444444}
         InProcServer32
            (Default) = C:\MyDir\MyCommand.dll
            ThreadingModel = Apartment
   MyProgram.1
      (Default) = MyProgram Application
      Shellex
         DataHandler
            (Default) = {00000000-1111-2222-3333-444444444444}
在这之前,它就像:

HKEY_CLASSES_ROOT
   .fileType
      (Default) = MyProgram.1
   CLSID
      {00000000-1111-2222-3333-444444444444}
         InProcServer32
            (Default) = C:\MyDir\MyCommand.dll
            ThreadingModel = Apartment
   MyProgram.1
      (Default) = MyProgram Application
      Shellex
         DataHandler
            {00000000-1111-2222-3333-444444444444} = 
            'Friendly Name'

希望这篇文章能防止其他人犯同样的错误。

无法判断RegisterInprocServer()函数是否编写了正确的密钥。我们甚至无法判断您是否犯了一个简单的错误,例如试图在64位版本的Windows上使用此DLL的32位版本。在当前状态下,无法获取有关此问题的帮助。无法判断RegisterInprocServer()函数是否正在写入正确的密钥。我们甚至无法判断您是否犯了一个简单的错误,例如试图在64位版本的Windows上使用此DLL的32位版本。在当前状态下,您无法获得此问题的帮助。