@@ -71,6 +71,29 @@ function Update-ServiceStatus {
7171 $svcControlBlock = {
7272 $group = $_.Group
7373 $computerName = $_.Name
74+ # Create a CIM session preferring DCOM to avoid requiring WinRM on the target machine.
75+ # CIM instances become deserialized when crossing runspace boundaries and lose their
76+ # session context, causing Invoke-CimMethod to attempt a new WinRM connection by default.
77+ # Using DCOM avoids this WinRM dependency for machines where WinRM is not configured.
78+ $splatCimDcomOption = @ {
79+ Protocol = " Dcom"
80+ }
81+ $cimDcomOption = New-CimSessionOption @splatCimDcomOption
82+ $splatCimSessionDcom = @ {
83+ ComputerName = $computerName
84+ SessionOption = $cimDcomOption
85+ ErrorAction = " Stop"
86+ }
87+ try {
88+ $cimSession = New-CimSession @splatCimSessionDcom
89+ } catch {
90+ # Fall back to default protocol (WinRM) if DCOM is unavailable
91+ try {
92+ $cimSession = New-CimSession - ComputerName $computerName - ErrorAction " Stop"
93+ } catch {
94+ $cimSession = $null
95+ }
96+ }
7497 $servicePriorityCollection = $group.ServicePriority | Select-Object - unique | Sort-Object - Property @ { Expression = { [int ]$_ }; Descending = $action -ne ' stop' }
7598 foreach ($priority in $servicePriorityCollection ) {
7699 $services = $group | Where-Object { $_.ServicePriority -eq $priority }
@@ -104,6 +127,23 @@ function Update-ServiceStatus {
104127 $invokeResults = @ ()
105128 foreach ($service in $servicesToRestart ) {
106129 if ($Pscmdlet.ShouldProcess (" Sending $action request to service $ ( $service.ServiceName ) on $ ( $service.ComputerName ) " )) {
130+ # Get a fresh CIM instance via the DCOM session to avoid issues with deserialized
131+ # CIM objects crossing runspace boundaries without their session context.
132+ if ($cimSession ) {
133+ try {
134+ $splatGetFreshCim = @ {
135+ CimSession = $cimSession
136+ Namespace = " root\cimv2"
137+ Query = " SELECT * FROM Win32_Service WHERE Name = '$ ( $service.ServiceName ) '"
138+ }
139+ $freshCimObj = Get-CimInstance @splatGetFreshCim
140+ if ($freshCimObj ) {
141+ $service._CimObject = $freshCimObj
142+ }
143+ } catch {
144+ # Fall back to using the existing deserialized CIM object if session refresh fails
145+ }
146+ }
107147 # Invoke corresponding CIM method
108148 $invokeResult = Invoke-CimMethod - InputObject $service._CimObject - MethodName $methodName
109149 $invokeResults += [psobject ]@ {
@@ -123,7 +163,19 @@ function Update-ServiceStatus {
123163 foreach ($result in ($invokeResults | Where-Object CheckPending -eq $true )) {
124164 try {
125165 # Refresh Cim instance - not using Get-DbaCmObject because module is not loaded here, but it only refreshes existing object
126- $result.Service._CimObject = $result.Service._CimObject | Get-CimInstance
166+ if ($cimSession ) {
167+ $splatRefreshCim = @ {
168+ CimSession = $cimSession
169+ Namespace = " root\cimv2"
170+ Query = " SELECT State FROM Win32_Service WHERE Name = '$ ( $result.Service.ServiceName ) '"
171+ }
172+ $refreshedCimObj = Get-CimInstance @splatRefreshCim
173+ if ($refreshedCimObj ) {
174+ $result.Service._CimObject = $refreshedCimObj
175+ }
176+ } else {
177+ $result.Service._CimObject = $result.Service._CimObject | Get-CimInstance
178+ }
127179 } catch {
128180 $result.ServiceExitCode = -3
129181 $result.ServiceState = ' Unknown'
@@ -177,6 +229,11 @@ function Update-ServiceStatus {
177229 $result
178230 }
179231 }
232+ # Clean up the CIM session created for DCOM connections
233+ if ($cimSession ) {
234+ Remove-CimSession - CimSession $cimSession - ErrorAction " SilentlyContinue"
235+ $cimSession = $null
236+ }
180237}
181238
182239$actionText = switch ($action ) { stop { ' stopped' }; start { ' started' }; restart { ' restarted' } }
0 commit comments