2015-03-12 3 views
1

Во время массивного обновления кода из состава VC6, VS2003 и VS2005 я столкнулся с проблемой, когда VS2010 не ведет себя как VS2003 сделал. Приложение сканирует каталог DLL и пытается загрузить их по одному. Это делается здесь: шоуИмпорт DLL не работает (VS2003 - VS2010, многопотоковая многопоточная DLL)

CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName) 
{ 
    ASSERT(szPluginName); 
    ASSERT(AfxIsValidString(szPluginName)); 

    m_csFullpath = szPluginName; 
    m_hModule = LoadLibrary(m_csFullpath); 
    m_pInterface = (IConfigDllInterface *) NULL; 
    pInterface pPtr = pInterface(NULL); 

    if (m_hModule != NULL) 
    { 
     // If we loaded the DLL get the interface pointer 
     pPtr = pInterface(GetProcAddress(m_hModule, "GetInterface")); 
    } 
    if (pPtr != NULL) 
    { 
     pPtr(&m_pInterface); 
    } 
    else 
    { 
     ::FreeLibrary(m_hModule); 
     m_hModule = HMODULE(NULL); 
    } 
} 

Все DLL, как загружаются: ... 'GenConfig.exe': Loaded 'C: \ SRC \ Debug \ Config \ GenLogonConfig.dll', Символы загружены. 'GenConfig.exe': загружен 'C: \ src \ Debug \ config \ GenReportConfig.dll', загружены символы. 'GenConfig.exe': загружен 'C: \ src \ Debug \ config \ ImportConfig.dll', загружены символы. ...

Каждая DLL имеет идентичную реализация GetInterface показана ниже:

CConfigDllInterfaceImpl<CParentDlg> gdllObj; 

BOOL GetInterface(IConfigDllInterface **ppPtr) 
{ 
    *ppPtr = &gdllObj; 

    // Temporary edit to test if gdllObj is set to proper parent. 
    CString name; 
    name = gdllObj.GetDisplayName(); 
    // End edit 

    return true; 
} 

С шаблоном, как показано ниже:

__declspec(selectany) UINT guiAdvise; 

template <class T> class CConfigDllInterfaceImpl : public IConfigDllInterface 
{ 
public: 
    CConfigDllInterfaceImpl() 
    { 
     guiAdvise = RegisterWindowMessage(_T("GenConfig")); 
     m_pDlg = NULL; 
    } 

    virtual LPCTSTR GetDisplayName() const 
    { 
     static CString csTemp; 

     csTemp.LoadString(IDS_DISPLAY_NAME); 
     return csTemp; 
    } 

    // Can't be virtual because it uses the template T argument 
    BOOL   DoModal(HWND hParent) 
    { 
     ASSERT(IsWindow(hParent)); 
     if (m_pDlg == (T *) NULL) 
     { 
      m_pDlg = new T(CWnd::FromHandle(hParent)); 
      return m_pDlg->Create(); 
     } 
     else if (IsWindow(m_pDlg->GetSafeHwnd())) 
     { 
      m_pDlg->PostMessage(guiAdvise, eAdviseSwitchViews); 
      m_pDlg->SetActiveWindow(); 
     } 
     return TRUE; 
    } // SNIP... 

Я могу сказать, что мой шаблон не правильно регистрации его предполагаемому родителю. GetDisplayName возвращает "". Мое подозрение, причина моей проблемы в том, что я принял решение месяц назад, чтобы изменить все на Multithreaded DLL из Multithreaded. Это все проекты MFC, и казалось, что самый простой и простой способ просто использовать _AFXDLL и сделать все правильно компилируемым и связанным. Все остальные мои проекты работают нормально, но я считаю, что из-за загрузки этой DLL:

CConfigDllInterfaceImpl gdllObj;

Больше не работает так, как раньше.

Итак, вопрос 1: Является ли мое подозрение правильным? Или я полностью вне базы? Вопрос 2: Если мое подозрение правильное, как мне обойти это? На данный момент это не вариант возврата к многопоточности.

Заранее спасибо.

+0

Вы перестроили все свои DLL-файлы с помощью VS2010? –

+0

Да. Все части того же решения. – milenko121175

+0

Убедитесь, что ваши ресурсы не были потеряны в обновлении. –

ответ

0

У меня наконец-то есть время, чтобы вернуться к ответу на это. Коллин Дофине был прав в том, что это проблема с ресурсами. Я не знаю, почему VS2003 отличается от VS2010, но решение было очень простым.

CConfigPlugin::CConfigPlugin(LPCTSTR szPluginName) 
{ 
    ASSERT(szPluginName); 
    ASSERT(AfxIsValidString(szPluginName)); 

    // Save off current Afx resource handle. 
    HINSTANCE hCurrentAfx = AfxGetResourceHandle(); // <--- Didn't need to 
                // do this before. 

    m_csFullpath = szPluginName; 
    m_hModule = NULL; 
    m_hModule = LoadLibrary(m_csFullpath); 
    m_pInterface = (IConfigDllInterface *) NULL; 
    pInterface pPtr = pInterface(NULL); 

    if (m_hModule != NULL) 
    { 
     AfxSetResourceHandle(m_hModule); // <--- here is where the resources 
              // get properly set. This is the 
              // solution to the problem. 

     // If we loaded the DLL get the interface pointer 
     pPtr = pInterface(GetProcAddress(m_hModule, "GetInterface")); 
    } 
    if (pPtr != NULL) 
    { 
     pPtr(&m_pInterface); 
    } 
    else 
    { 
     ::FreeLibrary(m_hModule); 
     m_hModule = HMODULE(NULL); 
    } 

    // Now put Afx back. 
    AfxSetResourceHandle(hCurrentAfx); 
} 

Я надеюсь, что это поможет кому-то еще. Несколько дней я застрял на этом.