question

thiagosgarcia avatar image
0 Votes"
thiagosgarcia asked thiagosgarcia published

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!



windows-server-powershell
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

0 Answers