在基于MFC的組件程序中加入自刪除技巧
發表時間:2024-02-13 來源:明輝站整理相關軟件相關文章人氣:
[摘要]作者:Alexei Evdokimov 譯自:CodeGuru 使用MFC實現COM組件時,經常節省許多開發時間。例如,使用AppWizard生成的基于MFC的COM dll工程,已經自動的提供了DllRegisterServer功能的實現。然而,卻沒有自動生成DllUnregisterServ...
作者:Alexei Evdokimov 譯自:CodeGuru
使用MFC實現COM組件時,經常節省許多開發時間。例如,使用AppWizard生成的基于MFC的COM dll工程,已經自動的提供了DllRegisterServer功能的實現。然而,卻沒有自動生成DllUnregisterServer功能。一般情況下,DllUnregisterServer對于程序是不可缺少的,因為一個完整的程序,不僅需要自注冊功能,同時也需要自卸載功能。
基于MFC實現DllRegisterServer()的方法是調用COleObjectFactory::UpdateRegistryAll()。這個方法有一個未公開的參數-(BOOL bRegister = TRUE) - 因此,我們猜測通過調用COleObjectFactory::UpdateRegistry(FALSE)將能夠實卸載COM dll的功能。但是,事實并非如此。通過分析源代碼,我們能夠知道COleObjectFactory::UpdateRegistryAll(BOOL bRegister)通過同樣的BOOL值調用COleObjectFactory::UpdateRegistry(BOOL bRegister),但是COleObjectFactory::UpdateRegistry(BOOL bRegister)的實現調用UpdateRegistry(LPCTSTR lpszProgID)函數,這個調用僅當bRegister為TRUE時注冊組件,否則什么都不做!
所以,有必要寫我們自己的DllUnregisterServer()。下面的代碼能夠實現基于MFC的DllUnregisterServer(),并且使用非常的簡單。使用方法:
- 創建文件DllUnregisterServer_MFC_Impl.inl
- 把下面的代碼拷貝/粘貼到新建的文件中
- 在dll的主文件.cpp中(dll_name.cpp)加入:
#include "DllUnregisterServer_MFC_Impl.inl"
- 在dll_name.def文件的EXPORTS片斷中加入:
DllUnregisterServer PRIVATE
完成!現在你可以使用"regsvr32 /u dll_name.dll"完成組件的卸載了。
以下代碼測試環境為VC++ 5.0, VC++ 5.0 SP3, VC++ 6.0,ANSI環境。也可用于UNICODE環境。
//**************************************************************************
// Date : 11.15.98
// Header : DllUnregisterServer_MFC_Impl.inl
//
// Desc.: DllUnregisterServer() helper for the inproc servers that were
// registered via MFC’s COleObjectFactory::UpdateRegistryAll()
//
// Usage:
// Add ’#include "DllUnregisterServer_MFC_Impl.inl"’ to the end of
// the main dll file (i.e. dll_name.cpp).
//
// Add ’DllUnregisterServer PRIVATE’ to EXPORTS section of the
// dll_name.def.
//
// Caution:
// Code below uses undocumented, internal MFC data structures
// and functions. Therefore, probably, it will be necessary to modify
// it, according to the changes in the future versions of MFC.
// Code below is based on the COleObjectFactory::UpdateRegistryAll(),
// in srcolefact.cpp. (srcolereg.cpp - is actual implementation of
// all registry work).
//**************************************************************************
#include "stdafx.h"
// workaround MFC bug - no #ifndef/#endif for afximpl.h header
#if !defined(CRIT_OBJECTFACTORYLIST)
#include <..srcafximpl.h>
#endif //!CRIT_OBJECTFACTORYLIST
//**************************************************************************
static HRESULT UnregisterCOMObject(REFCLSID p_clsid)
{
LPOLESTR t_wzProgID(NULL);
// get ProgID from CLSID and unregister...
HRESULT t_hr = ::ProgIDFromCLSID(p_clsid, &t_wzProgID);
if(FAILED(t_hr))
return t_hr;
// convert OLESTR to LPTSTR
CString t_strProgID(t_wzProgID);
LPCTSTR t_szProgID = t_strProgID.operator LPCTSTR();
// free memory
::CoTaskMemFree(t_wzProgID);
// unregister...
if(AfxOleUnregisterServerClass(p_clsid,
t_szProgID,
t_szProgID,
t_szProgID,
OAT_DISPATCH_OBJECT))
return S_OK;
else
return E_FAIL;
}
//**************************************************************************
// by exporting DllUnregisterServer, you can use regsvr.exe
STDAPI DllUnregisterServer(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
for(COleObjectFactory* pFactory = pModuleState->m_factoryList;
pFactory != NULL;
pFactory = pFactory->m_pNextFactory)
{
HRESULT t_hr = UnregisterCOMObject(pFactory->GetClassID());
if(FAILED(t_hr))
{
AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
return t_hr;
}
}
AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
#ifdef _AFXDLL
AfxLockGlobals(CRIT_DYNLINKLIST);
// register extension DLL factories
for(CDynLinkLibrary* pDLL = pModuleState->m_libraryList;
pDLL != NULL;
pDLL = pDLL->m_pNextDLL)
{
for(pFactory = pDLL->m_factoryList;
pFactory != NULL;
pFactory = pFactory->m_pNextFactory)
{
HRESULT t_hr = UnregisterCOMObject(pFactory->GetClassID());
if(FAILED(t_hr))
{
AfxUnlockGlobals(CRIT_DYNLINKLIST);
return t_hr;
}
}
}
AfxUnlockGlobals(CRIT_DYNLINKLIST);
#endif
return S_OK;
}
//**************************************************************************
// end of DllUnregisterServer_MFC_Impl.inl