Skip to content

Commit 99a4a90

Browse files
Update-ServiceStatus - Fix WinRM error on machines without WinRM configured (#10274)
1 parent 552b77a commit 99a4a90

2 files changed

Lines changed: 59 additions & 2 deletions

File tree

private/functions/Update-ServiceStatus.ps1

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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' } }

tests/appveyor.prep.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ $null = New-Item -Path C:\Users\appveyor\Documents\DbatoolsExport -ItemType Dire
5858
Write-Host -Object "appveyor.prep: Creating temp directory" -ForegroundColor DarkGreen
5959
$null = New-Item -Path C:\Temp -ItemType Directory
6060

61-
Write-Host -Object "appveyor.prep: Configuring WSMan (see #9782)" -ForegroundColor DarkGreen
61+
Write-Host -Object "appveyor.prep: Configuring WSMan" -ForegroundColor DarkGreen
6262
$null = Set-WSManQuickConfig -Force
6363

6464
Write-Host -Object "appveyor.prep: Trust SQL Server Cert (now required)" -ForegroundColor DarkGreen

0 commit comments

Comments
 (0)