2013-07-31 3 views
1

Я пытаюсь написать расширение оболочки обработчика данных. В Windows Dev Center говорится: «Обработчик данных вызывается, когда операция drag-and-drop выполняется на объектах dragShell, что позволяет предоставить дополнительные форматы буфера обмена для целевой цели». И я пытаюсь получить выбранный каталог файлов сразу после его копирования или перетаскивания.COM: DllGetClassObject не вызван для расширения оболочки DataHandler

Я вижу, что GUID был зарегистрирован в реестре, а DllMain и DllRegisterServer были вызваны во время реестра. Но DllGetClassObject никогда не вызывался каким-либо процессом. Я ожидаю, что explorer.exe вызовет его при копировании или перетаскивании файла.

Я уверен, что я скомпилирую dll под конфигурацией x64, так как моя ОС - это 64-разрядная версия Windows 7. CLSID создается с помощью инструмента «создать GUID» в VS 2010. После регистрации я вижу, что CLSID находится под подразделением DataHandler, который находится в режиме shellex. Также полный каталог dll находится в этой точке входа реестра CLSID. Поэтому я не могу придумать, почему он не загружает мою dll.

Хотя я могу найти некоторые статьи о расширении оболочки, но большинство из них касается других обработчиков. Релевантно только один на ссылку ниже:

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() правильные ключи. Мы даже не можем сказать, допустили ли вы простую ошибку, например, пытаетесь использовать 32-разрядную версию этой DLL для 64-разрядной версии Windows. Вы не можете получить помощь по этому вопросу в текущем состоянии. –

ответ

1

Наконец выяснить, где я делаю неправильно.

Я использовал файлы reg.h/cpp в примере ContextMenu и только изменил несколько мест. Фактически структуры дерева реестра для 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' 

Надеюсь, этот пост может помешать другим людям сделать ту же самую ошибку.

Смежные вопросы