2013-07-31 57 views
1

我想写一个数据处理程序外壳扩展。在Windows开发中心上,它说:“在对dragShell对象执行拖放操作时调用数据处理程序,它使您能够为放置目标提供额外的剪贴板格式。”我试图在复制或拖动后立即获取选定的文件目录。COM:DllGetClassObject不呼吁DataHandler外壳扩展

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

我很确定我编译在x64配置下的DLL,因为我的操作系统是Windows 7 64位。 CLSID是使用VS 2010中的“创建GUID”工具创建的。注册后,我可以看到CLSID位于数据处理器的子密钥下,该密钥处于shellex下。此外,dll的完整目录位于该CLSID注册表入口点。所以我想不出为什么它不会加载我的dll。

尽管我可以找到一些关于shell扩展的文章,但其中大部分都是关于其他处理程序的。唯一有关的一个下面的链接:

http://msdn.microsoft.com/en-us/library/windows/desktop/cc144163(v=vs.85).aspx

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

这里是的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; 
} 
+1

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

回答

1

最后弄清楚,我是做错了。

我在ContextMenu例子中使用了reg.h/cpp文件,只修改了几个地方。事实上,ContextMenuHandlers和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' 

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