none
dllregisterserver failed with error code 0x80004005 RRS feed

  • Question

  • I had one project COM dll which was developed using Visual studio 2012. I was able to register the COM dll manually using regsvr32

    Recently I migrated into Visual studio 2017 and after migration, I am not able to register same dll manually using regsvr32, giving following error..

    dllregisterserver failed with error code 0x80004005

    I am just opening CMD as Administrator then executing regsvr32 "dll name"

    I tried by disabling UAC notification. Also I have full control permission the file and folder..

    Can anybody suggest me the solution for this. ?

    Monday, July 29, 2019 12:03 PM

Answers

All replies

  • I had one project COM dll which was developed using Visual studio 2012. I was able to register the COM dll manually using regsvr32

    Recently I migrated into Visual studio 2017 and after migration, I am not able to register same dll manually using regsvr32, giving following error..

    dllregisterserver failed with error code 0x80004005

    I am just opening CMD as Administrator then executing regsvr32 "dll name"

    I tried by disabling UAC notification. Also I have full control permission the file and folder..

    Can anybody suggest me the solution for this. ?

    It's not clear what "dll name" represents.  Does it include the fully qualified path to the COM dll?

    You can debug the COM registration as follows:

    In your project that builds the COM dll set the debugging options in the project properties so that it runs regsvr32.exe and pass the full path to the COM dll as a command line argument.  Set a breakpoint in the source for the dll on the DllRegisterServer method.  Run VS as Administrator with elevated privileges and start debugging the COM dll project.  After regsvr32.exe loads your COM dll your breakpoint at DllRegisterServer should be hit.  You can then step through the registration code to determine the source of the error.

    Monday, July 29, 2019 12:43 PM
  • yes it includes fully qualified path to the COM dll. I was trying debug but dllregisterserver is return error code 0x80004005..

    Monday, July 29, 2019 1:37 PM
  • yes it includes fully qualified path to the COM dll. I was trying debug but dllregisterserver is return error code 0x80004005..

    Did you try debugging into the DllRegisterServer function as suggested?

    BTW, 0x80004005 is E_FAIL (Unspecified Error).  So it provides no insight into the problem.

    • Edited by RLWA32 Monday, July 29, 2019 2:14 PM
    Monday, July 29, 2019 1:51 PM
  • Hi, I tried to debug and found that it is failing in UpdateRegistryFromResourceD..

    _ATL_REGMAP_ENTRY

           rmEntries[] = {

            {

    OLESTR( "CLASS_ID"), szCLSID },

            {

    OLESTR( "PROG_ID"), T2OLE( pObjectInfo[dwIdx].GetProgID().c_str() ) },

            {

    OLESTR( "DESCRIPTION"), T2OLE( pObjectInfo[dwIdx].GetName().c_str() ) },

            {

    NULL, NULL}

        };

    StringFromGUID2( pObjectInfo[

    dwIdx].GetCLSID(), szCLSID, sizeof( szCLSID ) / sizeof( szCLSID[0] ) );

    hr = _Module.UpdateRegistryFromResourceD(

    IDR_REGISTRY, bRegister, rmEntries );

    UpdateRegistryFromResourceD fails and it is not able update the registry in VS 2017.

    Can anybody suggest that why is this failing and unable to update registry.

    Mrutyunjaya

    Monday, August 12, 2019 1:30 PM
  • You should step into the ATL source code while debugging to find the specific point of failure.   That should enable you to determine the actual reason.

    In my copy of VS2015 the ATL source code always returns E_FAIL from UpdateRegistryFromResourceD.

    	// Resource-based Registration
    	virtual HRESULT WINAPI UpdateRegistryFromResourceD(
    		_In_opt_z_ LPCTSTR lpszRes,
    		_In_ BOOL bRegister,
    		_In_opt_ struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw()
    	{
    		(lpszRes);
    		(bRegister);
    		(pMapEntries);
    		return E_FAIL;
    	}
    	
    	virtual HRESULT WINAPI UpdateRegistryFromResourceD(
    		_In_ UINT nResID,
    		_In_ BOOL bRegister,
    		_In_opt_ struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw()
    	{
    		(nResID);
    		(bRegister);
    		(pMapEntries);
    		return E_FAIL;
    	}

    I suggest you update your code to use other available ATL registration macros/functions for your .rgs resources

    Update:

    Also, see https://blogs.msdn.microsoft.com/dsnotes/2013/12/11/com-cannot-register-a-com-dll-using-atlccommoduleregisterserver/

    Apparently, this change was made beginning with VS2013.

    • Edited by RLWA32 Monday, August 12, 2019 4:39 PM added update
    Monday, August 12, 2019 2:49 PM
  • class ATL_NO_VTABLE CAtlComModuleT : public CAtlModuleT<CComModule>
    {

    public:

    #ifdef _ATL_STATIC_REGISTRY                                     
     #define UpdateRegistryFromResource UpdateRegistryFromResourceS  
    #else                                                           
     #define UpdateRegistryFromResource UpdateRegistryFromResourceD  
    #endif                                                          

     // Resource-based Registration                             
    #ifdef _ATL_STATIC_REGISTRY                                     
     // Statically linking to Registry Component                 
     HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes,
      BOOL bRegister,
      struct _ATL_REGMAP_ENTRY* pMapEntries = NULL);
     HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID,
      BOOL bRegister,
      struct _ATL_REGMAP_ENTRY* pMapEntries = NULL);
    #else                                                           
     HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes,
      BOOL bRegister,
      struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) {
      USES_CONVERSION;
      return UpdateRegistryFromResourceDHelper(T2COLE(lpszRes),
       bRegister, pMapEntries);
     }
     HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID,
      BOOL bRegister,
      struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) {
      return UpdateRegistryFromResourceDHelper(
       (LPCOLESTR)MAKEINTRESOURCE(nResID),
       bRegister, pMapEntries);
     }
    #endif                      
    };

    extern CAtlComModuleT _ModuleT;

    /////////////////////////////////////////////////////////////////////////////
    Function where I am calling

    HRESULT WINAPI UpdateRegistry( DWORD dwIdx, BOOL bRegister )
    {
        USES_CONVERSION;

        OLECHAR         szCLSID[64];
        HRESULT         hr;

        _ATL_REGMAP_ENTRY       rmEntries[] = {
            { OLESTR( "CLASS_ID"), szCLSID },
            { OLESTR( "PROG_ID" ), T2OLE( pObjectInfo[dwIdx].GetProgID().c_str() ) },
            { OLESTR( "DESCRIPTION" ), T2OLE( pObjectInfo[dwIdx].GetName().c_str() ) },
            { NULL, NULL }
        };

        StringFromGUID2( pObjectInfo[dwIdx].GetCLSID(), szCLSID, sizeof( szCLSID ) / sizeof( szCLSID[0] ) );

        hr = _Module.UpdateRegistryFromResourceD( IDR_REGISTRY, bRegister, rmEntries );

        return hr;
    }

    ///////////////////////////////////////////////////////////////////////////////*.rgs file


    HKCR
    {
     %PROG_ID%.1 = s '%DESCRIPTION%'
     {
      CLSID = s '%CLASS_ID%'
     }
     %PROG_ID% = s '%DESCRIPTION%'
     {
      CLSID = s '%CLASS_ID%'
      CurVer = s '%PROG_ID%.1'
     }
     NoRemove CLSID
     {
      ForceRemove %CLASS_ID% = s '%DESCRIPTION%'
      {
       ProgID = s '%PROG_ID%.1'
       VersionIndependentProgID = s '%PROG_ID%'
       InprocServer32 = s '%MODULE%'
       {
        val ThreadingModel = s 'Both'
       }
      }
     }
    }


    ////////////////////////////////////////////////////////////////////////

    UpdateRegistryFromResourceDHelper is not gettin resolved in VS 2017, I am trying to use VS 2017 or do I need to modify .rgs file..

    Could you please suggest ?

    Tuesday, August 13, 2019 12:39 PM
  • If you have a typical .rgs that contains what you need for registration then you should use the DECLARE_REGISTRY_RESOURCEID macro.

    If you want to use your own replaceable parameters in the .rgs file then you need to override CAtlModule::AddCommonRGSReplacements

    Tuesday, August 13, 2019 12:50 PM
  • Actually This is one component which registers multiple inproc com components. I mean that this is one COM dll but it will have multiple clsid and progid to register . So because of that reason I had to call Manually  UpdateRegistryFromResourceD in UpdateRegistry function which I have implemented. I have array of _ATL_REGMAP_ENTRY       rmEntries[] and trying to register one by one in a loop. UpdateRegistry is the call back function registered with WINAPI *pfnUpdateRegistry) member of _ATL_REGMAP_ENTRY .     

    I have mentioned .rgs file above. Do I need  any modification in .rgs file.

    This is working fine with Visual studio 2012. recently I have migrated to Visual Studio 2017 where UpdateRegistryFromResourceD fails with error code 0x80004005.

    I tried to implement as above to simulate as Visual Studio 2012. I mean to call as VS 2012 way by following how it calls internally in VS 2012.

    However UpdateRegistryFromResourceDHelper is missing in VS2017  which is called by UpdateRegistryFromResourceD in vs 2012.

    if you are suggesting to override CAtlModule::AddCommonRGSReplacements then can you please point to any sample if you are aware.

    Wednesday, August 14, 2019 4:41 AM
  • Actually This is one component which registers multiple inproc com components. I mean that this is one COM dll but it will have multiple clsid and progid to register . So because of that reason I had to call Manually  UpdateRegistryFromResourceD in UpdateRegistry function which I have implemented. I have array of _ATL_REGMAP_ENTRY       rmEntries[] and trying to register one by one in a loop. UpdateRegistry is the call back function registered with WINAPI *pfnUpdateRegistry) member of _ATL_REGMAP_ENTRY .     

    I have mentioned .rgs file above. Do I need  any modification in .rgs file.

    This is working fine with Visual studio 2012. recently I have migrated to Visual Studio 2017 where UpdateRegistryFromResourceD fails with error code 0x80004005.

    I tried to implement as above to simulate as Visual Studio 2012. I mean to call as VS 2012 way by following how it calls internally in VS 2012.

    However UpdateRegistryFromResourceDHelper is missing in VS2017  which is called by UpdateRegistryFromResourceD in vs 2012.

    if you are suggesting to override CAtlModule::AddCommonRGSReplacements then can you please point to any sample if you are aware.

    You can download a demo project that uses replaceable parameters in an .rgs file, the DECLARE_REGISTRY_RESOURCEID macro, and an AddCommonRGSReplacements override from RegTest.zip

    The demo contains -

    HKCR
    {
    	%PROGID%.1 = s '%DESCRIPTION%'
    	{
    		CLSID = s '%CLSID%'
    	}
    	%PROGID% = s '%DESCRIPTION%'
    	{		
    		CurVer = s '%PROGID%.1'
    	}
    	NoRemove CLSID
    	{
    		ForceRemove %CLSID% = s '%DESCRIPTION%'
    		{
    			ProgID = s '%PROGID%.1'
    			VersionIndependentProgID = s '%PROGID%'
    			ForceRemove Programmable
    			InprocServer32 = s '%MODULE%'
    			{
    				val ThreadingModel = s 'Both'
    			}
    			TypeLib = s '%TYPELIB%'
    			Version = s '1.0'
    		}
    	}
    }


    DECLARE_REGISTRY_RESOURCEID(IDR_TESTOBJ)

    // dllmain.h : Declaration of module class.
    
    class CRegTestModule : public ATL::CAtlDllModuleT< CRegTestModule >
    {
    public :
    	DECLARE_LIBID(LIBID_RegTestLib)
    	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_REGTEST, "{7F6E18ED-AFA8-4B2F-AC3F-30C1932280B8}")
    	HRESULT AddCommonRGSReplacements(IRegistrarBase *pRegistrar) throw()
    	{
    		HRESULT hr;
    		__super::AddCommonRGSReplacements(pRegistrar);
    		hr = pRegistrar->AddReplacement(L"PROGID", L"TestObj.Object");
    		hr = pRegistrar->AddReplacement(L"DESCRIPTION", L"TestObj Class");
    		hr = pRegistrar->AddReplacement(L"CLSID", L"{D6E2109B-AC26-4BA4-9297-BEF5D829F06F}");
    		hr = pRegistrar->AddReplacement(L"TYPELIB", L"{602AB1C9-0CD8-4506-AA02-263884ED3E3D}");
    		return hr;
    	}
    };
    
    extern class CRegTestModule _AtlModule;


    Wednesday, August 14, 2019 9:13 AM
  • Thanks for your reply. But in my case I need to register multiple CLSID, PROGID, ....

    Will it help to my scenario ? So which clsid , progid, I need to pass in below..

    hr = pRegistrar->AddReplacement(L"PROGID", L"TestObj.Object");
    hr = pRegistrar->AddReplacement(L"CLSID", L"{D6E2109B-AC26-4BA4-9297-BEF5D829F06F}");

    As I said that this is one dll which will have multiple clasid, progid.. to register. So I'm storing in _ATL_REGMAP_ENTRY       rmEntries[] and trying to register by calling UpdateRegistryFromResourceD ()..

    Mrutyunjaya

    Wednesday, August 14, 2019 9:28 AM
  • Thanks for your reply. But in my case I need to register multiple CLSID, PROGID, ....


    Well, the simplest solution is to use a fully formed .rgs for each COM class, each with its own resource ID referenced by DECLARE_REGISTRY_RESOURCEID macro.  No  user-defined replaceable parameters required.

    • Edited by RLWA32 Wednesday, August 14, 2019 9:38 AM
    Wednesday, August 14, 2019 9:36 AM
  • If you really want to stay with replaceable parameters and use a single .rgs file for all COM classes then you can use the following in each COM class header instead of the DECLARE_REGISTRY_RESOURCEID macro.   IDR_COMREG is the id for the .rgs resource that contains the replaceable parameters.  There is then no need for AddCommonRGSReplacements.  Obviously you would use different entries for the registry map in each class.

    	static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()
    	{
    		_ATL_REGMAP_ENTRY regEntries[] = 
    		{
    			{ L"PROGID", L"TestObj.Object" },
    			{ L"DESCRIPTION", L"TestObj Class" },
    			{ L"CLSID", L"{D6E2109B-AC26-4BA4-9297-BEF5D829F06F}" },
    			{ L"TYPELIB", L"{602AB1C9-0CD8-4506-AA02-263884ED3E3D}" },
    			{NULL, NULL}
    		};
    
    		 return _pAtlModule->UpdateRegistryFromResource(IDR_COMREG, bRegister, regEntries);
    	}
    


    • Edited by RLWA32 Wednesday, August 14, 2019 11:27 AM
    Wednesday, August 14, 2019 11:26 AM
  • Did you try this suggestion?
    Thursday, August 15, 2019 7:44 PM
  • then you can use the following in each COM class header instead of the DECLARE_REGISTRY_RESOURCEID macro.

    each COM class header : I did not get you here . I have one COM class header and I am calling UpdateRegistry in DllMain DLL_PROCESS_ATTACH in a loop since I have array of struct _ATL_REGMAP_ENTRY* pMapEntries.

    each struct _ATL_REGMAP_ENTRY* pMapEntries contains clsid, progid, description etc of coclasss of .idl file.

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    _pAtlModule->UpdateRegistryFromResource(IDR_COMREG, bRegister, regEntries); Are you using CComModule or any other class..

    Friday, August 16, 2019 7:49 AM
  • I uploaded a new demo so you can see exactly what I mean in my earlier post.  You can get it at RegTest2.zip

    CComModule was deprecated several years ago.  I used the ATL new project wizard to create the demo and so it uses AtlModule and the related derived classes as you can see from the declarations of the classes in the .h files.

    Edit:

    If you refer to the blog post from 2013 that I linked to earlier you will note that it advises CComModule has been deprecated since VS2003 and was completely removed in VS2013.

    • Edited by RLWA32 Friday, August 16, 2019 9:05 AM CComModule deprecation
    Friday, August 16, 2019 8:40 AM
  • Hi, I am not able to download your example. If it is fine for you then Can you please send to me in my email id

    mrutyunjaya.mahapatra@hotmail.com

    Mrutyunjaya

    Monday, August 19, 2019 8:36 AM
  • Well, you can see what I meant from the following snippets -

    Registration resource ( COMREG.rgs) shared by all COM objects in the dll -

    HKCR
    {
    	%PROGID%.1 = s '%DESCRIPTION%'
    	{
    		CLSID = s '%CLSID%'
    	}
    	%PROGID% = s '%DESCRIPTION%'
    	{		
    		CurVer = s '%PROGID%.1'
    	}
    	NoRemove CLSID
    	{
    		ForceRemove %CLSID% = s '%DESCRIPTION%'
    		{
    			ProgID = s '%PROGID%.1'
    			VersionIndependentProgID = s '%PROGID%'
    			ForceRemove Programmable
    			InprocServer32 = s '%MODULE%'
    			{
    				val ThreadingModel = s 'Both'
    			}
    			TypeLib = s '%TYPELIB%'
    			Version = s '1.0'
    		}
    	}
    }
    

    Class declaration for COM object TestObj -

    // CTestObj
    
    class ATL_NO_VTABLE CTestObj :
    	public CComObjectRootEx<CComMultiThreadModel>,
    	public CComCoClass<CTestObj, &CLSID_TestObj>,
    	public IDispatchImpl<ITestObj, &IID_ITestObj, &LIBID_RegTestLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
    {
    public:
    	CTestObj() : m_Name(L"TestObj")
    	{
    	}
    
    	static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()
    	{
    		_ATL_REGMAP_ENTRY regEntries[] = 
    		{
    			{ L"PROGID", L"TestObj.Object" },
    			{ L"DESCRIPTION", L"TestObj Class" },
    			{ L"CLSID", L"{D6E2109B-AC26-4BA4-9297-BEF5D829F06F}" },
    			{ L"TYPELIB", L"{602AB1C9-0CD8-4506-AA02-263884ED3E3D}" },
    			{NULL, NULL}
    		};
    
    		 return _pAtlModule->UpdateRegistryFromResource(IDR_COMREG, bRegister, regEntries);
    	}
    
    
    BEGIN_COM_MAP(CTestObj)
    	COM_INTERFACE_ENTRY(ITestObj)
    	COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()
    
    
    
    	DECLARE_PROTECT_FINAL_CONSTRUCT()
    
    	HRESULT FinalConstruct()
    	{
    		return S_OK;
    	}
    
    	void FinalRelease()
    	{
    	}
    
    public:
    
    
    
    	STDMETHOD(get_Name)(BSTR* pVal);
    	STDMETHOD(put_Name)(BSTR newVal);
    private:
    	CComBSTR m_Name;
    };
    

    Class declaration for COM object TestObj2 -

    class ATL_NO_VTABLE CTestObj2 :
    	public CComObjectRootEx<CComMultiThreadModel>,
    	public CComCoClass<CTestObj2, &CLSID_TestObj2>,
    	public IDispatchImpl<ITestObj2, &IID_ITestObj2, &LIBID_RegTestLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
    {
    public:
    	CTestObj2() : m_Name(L"TestObj2")
    	{
    	}
    
    	static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()
    	{
    		_ATL_REGMAP_ENTRY regEntries[] =
    		{
    			{ L"PROGID", L"TestObj2.Object" },
    			{ L"DESCRIPTION", L"TestObj2 Class" },
    			{ L"CLSID", L"{6A9D174B-AD53-4080-9B73-70D5A9FE4946}" },
    			{ L"TYPELIB", L"{602AB1C9-0CD8-4506-AA02-263884ED3E3D}" },
    			{ NULL, NULL }
    		};
    
    		return _pAtlModule->UpdateRegistryFromResource(IDR_COMREG, bRegister, regEntries);
    	}
    
    
    BEGIN_COM_MAP(CTestObj2)
    	COM_INTERFACE_ENTRY(ITestObj2)
    	COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()
    
    
    
    	DECLARE_PROTECT_FINAL_CONSTRUCT()
    
    	HRESULT FinalConstruct()
    	{
    		return S_OK;
    	}
    
    	void FinalRelease()
    	{
    	}
    
    public:
    
    	STDMETHOD(get_Name)(BSTR* pVal);
    	STDMETHOD(put_Name)(BSTR newVal);
    private:
    	CComBSTR m_Name;
    
    
    };
    

    Note that each class contains its own UpdateRegistry method that handles the replaceable parameters for that COM object.

    Class declaration for the ATL module derived from CAtlDllModuleT-

    class CRegTestModule : public ATL::CAtlDllModuleT< CRegTestModule >
    {
    public :
    	DECLARE_LIBID(LIBID_RegTestLib)
    	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_REGTEST, "{7F6E18ED-AFA8-4B2F-AC3F-30C1932280B8}")
    };
    


    Monday, August 19, 2019 9:47 AM
  • What is the class for _pAtlModule object. ? 

    Mrutyunjaya

     
    Monday, August 19, 2019 10:33 AM
  • It is a CAtlModule * pointer variable declared in atlbase.h
    Monday, August 19, 2019 10:58 AM
  • Where are you declaring in your code. or How are you using that ? That's wht I had main doubt ..

    -Mrutyunjaya

    Monday, August 19, 2019 11:08 AM
  • Where are you declaring in your code. or How are you using that ? That's wht I had main doubt ..

    The _pAtlModule global variable is managed by ATL.

    https://docs.microsoft.com/en-us/cpp/atl/reference/atl-global-variables?view=vs-2019#_patlmodule

    • Edited by RLWA32 Monday, August 19, 2019 11:23 AM
    Monday, August 19, 2019 11:17 AM
  • Have you made any progress?
    Wednesday, August 28, 2019 12:28 PM
  • yes, that issue is resolved . Thanks a lot for extended reply. ~mrutyunjaya
    • Marked as answer by MRUTYUNJAYA.M Friday, September 20, 2019 9:59 AM
    • Unmarked as answer by MRUTYUNJAYA.M Friday, September 20, 2019 10:39 AM
    Friday, September 20, 2019 9:59 AM
  • yes, that issue is resolved . Thanks a lot for extended reply. ~mrutyunjaya

    How was the issue resolved?

    Did you use any of my suggestions?

    Friday, September 20, 2019 10:00 AM
  • issue resolved through this ...

    _pAtlModule->UpdateRegistryFromResource(

    IDR_REGISTRY, bRegister, rmEntries );

    Mrutyunjaya

    Friday, September 20, 2019 10:38 AM
  • issue resolved through this ...

    _pAtlModule->UpdateRegistryFromResource(

    IDR_REGISTRY, bRegister, rmEntries );

    Mrutyunjaya

    So did I answer your questions and resolve the registration issue?
    Friday, September 20, 2019 10:43 AM
  • Yes, You have answered my question..Mrutyunjaya
    • Marked as answer by MRUTYUNJAYA.M Saturday, September 21, 2019 9:38 AM
    Saturday, September 21, 2019 9:37 AM
  • Yes, You have answered my question..Mrutyunjaya

    Then why do you mark your own response to my comment as an answer?

    It's nice that you say thank you, but you should mark the responses of others that assisted you as answers where they provided the solution to your problems.
    • Edited by RLWA32 Saturday, September 21, 2019 9:46 AM
    Saturday, September 21, 2019 9:43 AM