COM:DllGetClassObject不调用DataHandlershell扩展

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

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

我很确定我编译的x64configuration的DLL,因为我的操作系统是Windows 7 64位。 CLSID是使用VS 2010中的“创buildGUID”工具创build的。注册后,我可以看到CLSID在DataHandler的子键下。 此外,DLL的完整目录是在该CLSIDregistry入口点。 所以我想不出为什么它不加载我的DLL的任何理由。

尽pipe我可以find一些关于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; } 

最后找出我在做错的地方。

我在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' 

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