Windows Server headless installations are not able to manage COM+ components

Thiago Garcia 1 Reputation point
2021-03-19T01:30:45.927+00:00

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!

Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,456 questions
0 comments No comments
{count} votes