2013-07-31 85 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' 

希望這篇文章可以防止其他人犯同樣的錯誤。