Windows Server headless installations are not able to manage COM+ components
I've been digging into it for quite some time, and seems like some people did as well. Reference1 Reference2
Disclaimers:
- This is NOT an issue with the docker image. I was able to reproduce it in headless installations of Windows Server 2016 and 2019 as well as in docker servercore.
- I was able to make this work in windows:20H2 image. Althought this is not going to work for me because there are other things I need that this image doesn't offer.
I'm migrating some legacy applications to docker and there are COM+ dependencies. No problems with Desktop Experience instalations, but in headless installations (physical, virtual machines or docker containers) COM+ installation just doesn't work.
Listing all components, I get this response. Note that COMEXPS.CTrkEvntListener.1
wich is part of COM+ Explorer
application returns an error:
PS C:\> $comAdmin = New-Object -com ("COMAdmin.COMAdminCatalog")
PS C:\> $applications = $comAdmin.GetCollection("Applications")
PS C:\> $applications.Populate()
PS C:\> foreach ($application in $applications)
>> {
>> $components = $applications.GetCollection("Components",$application.key)
>> $components.Populate()
>> foreach ($component in $components)
>> {
>>
>> $dllName = $component.Value("DLL")
>> $componentName = $component.Name
>>
>> "Component Name:$componentName"
>> "DllName: $dllName`n"
>> }
>> }
Component Name:RemoteHelper.RemoteHelper
DllName: C:\Windows\system32\stclient.dll
Component Name:TxCTx.TransactionContext
DllName: C:\Windows\System32\comsvcs.dll
Component Name:TxCTx.TransactionContextEx
DllName: C:\Windows\System32\comsvcs.dll
Component Name:QC.Recorder
DllName: C:\Windows\System32\comsvcs.dll
Component Name:QC.ListenerHelper
DllName: C:\Windows\System32\comsvcs.dll
Component Name:QC.DLQListener
DllName: C:\Windows\System32\comsvcs.dll
Errors occurred accessing one or more objects - the ErrorInfo collection may have more detail
(Exception from HRESULT: 0x80110401)
At line:5 char:5
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
Component Name:COMEXPS.CTrkEvntListener.1
DllName:
Component Name:RemoteHelper.RemoteHelper
DllName: C:\Windows\system32\stclient.dll
Component Name:TxCTx.TransactionContext
DllName: C:\Windows\SysWOW64\comsvcs.dll
Component Name:TxCTx.TransactionContextEx
DllName: C:\Windows\SysWOW64\comsvcs.dll
Component Name:QC.Recorder
DllName: C:\Windows\SysWOW64\comsvcs.dll
Component Name:QC.ListenerHelper
DllName: C:\Windows\SysWOW64\comsvcs.dll
Component Name:Catsrv.CatalogServer
DllName: C:\Windows\system32\catsrv.dll
Component Name:EventPublisher.EventPublisher
DllName: C:\Windows\System32\comsvcs.dll
DllName: C:\Windows\System32\comsvcs.dll
Component Name:Mts.MtsGrp
DllName: C:\Windows\System32\comsvcs.dll
Component Name:Pdump.ProcessDump
DllName: C:\Windows\System32\comsvcs.dll
So, except for the error before line Component Name:COMEXPS.CTrkEvntListener.1
, everything is default there. You also can add applications to COM+ registry:
PS C:\Windows\System32> $comAdmin = New-Object -comobject COMAdmin.COMAdminCatalog
PS C:\Windows\System32> $apps = $comAdmin.GetCollection("Applications")
PS C:\Windows\System32> $apps.Populate();
PS C:\Windows\System32> $applicationName= "ApplicationName"
PS C:\Windows\System32> $appExistCheckApp = $apps | Where-Object {$_.Name -eq $applicationName}
PS C:\Windows\System32> $newApp1 = $apps.Add()
PS C:\Windows\System32> $newApp1.Value("Name") = $applicationName
PS C:\Windows\System32> $newApp1.Value("Identity") = "nt authority\localservice"
PS C:\Windows\System32> $apps.SaveChanges()
1
PS C:\Windows\System32> $apps.Populate();
PS C:\Windows\System32> $apps
Key Name Valid
--- ---- -----
{9EB3B62C-79A2-11D2-9891-00C04F79AF51} COM+ Utilities True
{7B4E1F3C-A702-11D2-A336-00C04F7978E0} COM+ QC Dead Letter Queue Listener True
{9E18F23F-72BD-44A2-8DC7-7B5CAECF5E21} ApplicationName True
{01885945-612C-4A53-A479-E97507453926} COM+ Explorer True
{6B97138E-3C20-48D1-945F-81AE63282DEE} COM+ Utilities (32 bit) True
{02D4B3F1-FD88-11D1-960D-00805FC79235} System Application True
This actually works fine, and you can see that ApplicationName
has been added.
The issue is when you try to add a DLL Component to any of the configured applications:
PS C:\> $installResults = $comAdmin.InstallComponent("{9E18F23F-72BD-44A2-8DC7-7B5CAECF5E21}", " C:\mydll.dll", "", "");
(Exception from HRESULT: 0x80110401)
At line:1 char:1
+ $installResults = $comAdmin.InstallComponent("{9E18F23F-72BD-44A2-8DC ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
or
PS C:\> regsvr32 /s ./mydll.dll
The first attemp returns an error, the second one just does nothing.
I noticed that the error is the same as when you're listing components. Maybe InstallComponent
function is calling this list at some point and failing because of this error.
I was able to see that application
and component
removal are not working or disabled:
PS C:\> $applications.Remove(3)
PS C:\> $applications.SaveChanges()
The delete function has been disabled for this object (Exception from HRESULT: 0x8011042B)
At line:1 char:1
+ $applications.SaveChanges()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
PS C:\> $components.Remove(0)
PS C:\> $components.SaveChanges()
Errors occurred accessing one or more objects - the ErrorInfo collection may have more detail
(Exception from HRESULT: 0x80110401)
+ $components.SaveChanges()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
IMPORTANT: The very same error that is returned in component listing, is also returned in InstallComponent
and SaveChanges
functions. Maybe because of the same reasons. (?)
I could track this component in a Windows Server with Desktop UI to a DLL. I checked this DLLs dependencies and it seems that all of them are in the image, but the component's one is missing:
PS C:\> ls C:\Windows\System32\comuid.dll
ls : Cannot find path 'C:\Windows\System32\comuid.dll' because it does not exist.
At line:1 char:1
+ ls C:\Windows\System32\comuid.dll
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Windows\System32\comuid.dll:String) [Get-ChildItem], ItemNotFou
ndException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
But even copying this DLL to the machine or image where it is missing the error persists.
Seems like that the absence of the file in the original image makes the component stay in Fail state:
PS C:\> $component
Key Name Valid
--- ---- -----
{2C3E140B-7A0D-42D1-B2AA-D343500A90CF} COMEXPS.CTrkEvntListener.1 False
Also, hence that the error is caused by a COM+ Explorer DLL that doesn't event should exist at a non-desktop environment. At least I think.
I'll be happy to give any additional information about the problem.
Thanks a lot!