關於一個模塊中所有rgs文件中有註冊項無法全部寫入註冊表的問題

1、問題情形

創建ATL項目時,使用VC每增加一個COM類,就會生成一個對應的rgs文件。
在vista及win7系統中,如果增加了HKLM註冊表項,而生成的程序並不是以管理員身份運行時,就會出現本該寫入HKCU的某些註冊表項並沒有被寫入。

2、問題原因

由於調用DllRegisterServer時,如果加載的rgs文件中的註冊表項中的某一項寫入註冊表失敗,後面的就不寫入了。
以下是ATL源碼:可以看出,註冊如果出錯,就break了。

ATLINLINE ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID)
{
	ATLASSERT(pComModule != NULL);
	if (pComModule == NULL)
		return E_INVALIDARG;
	ATLASSERT(pComModule->m_hInstTypeLib != NULL);

	HRESULT hr = S_OK;

	for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++)
	{
		if (*ppEntry != NULL)
		{
			_ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
			if (pCLSID != NULL)
			{
				if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
					continue;
			}
			hr = pEntry->pfnUpdateRegistry(TRUE);
			if (FAILED(hr))
				break;
			hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid,
				pEntry->pfnGetCategoryMap(), TRUE );
			if (FAILED(hr))
				break;
		}
	}

	if (SUCCEEDED(hr) && bRegTypeLib)
		hr = AtlRegisterTypeLib(pComModule->m_hInstTypeLib, 0);

	return hr;
}

3、解決辦法:

查看ATL源代碼,DllRegisterServer的實現源碼是這樣的:

	HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw()
	{
		LCID lcid = GetThreadLocale();
		SetThreadLocale(LOCALE_SYSTEM_DEFAULT);
		// registers object, typelib and all interfaces in typelib
		T* pT = static_cast<T*>(this);
		HRESULT hr = pT->RegisterAppId();
		if (SUCCEEDED(hr))
			hr = pT->RegisterServer(bRegTypeLib);
		SetThreadLocale(lcid);
		return hr;
	}

因此,只需要在定義模塊的module類中重寫RegisterServer即可。

    HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw()
    {
        (pCLSID);
        (bRegTypeLib);

        HRESULT hr = S_OK;

#ifndef _ATL_NO_COM_SUPPORT
        for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++)
        {
            if (*ppEntry != NULL)
            {
                _ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
                if (pCLSID != NULL)
                {
                    if (!IsEqualGUID(*pCLSID, *pEntry->pclsid))
                        continue;
                }
                hr = pEntry->pfnUpdateRegistry(TRUE);
                if (FAILED(hr))
                    continue;
                hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid,
                    pEntry->pfnGetCategoryMap(), TRUE );
                if (FAILED(hr))
                    continue;
            }
        }

        if (SUCCEEDED(hr) && bRegTypeLib)
            hr = AtlRegisterTypeLib(_AtlComModule.m_hInstTypeLib, 0);
#endif

#ifndef _ATL_NO_PERF_SUPPORT

        if (SUCCEEDED(hr) && _pPerfRegFunc != NULL)
            hr = (*_pPerfRegFunc)(_AtlBaseModule.m_hInst);

#endif

        return hr;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章