Skip to content

Commit 71cf1e3

Browse files
authored
fix: capture cmdlet warnings to prevent stdout contamination breaking DSC JSON parsing (#2000)
* fix: capture cmdlet warnings to prevent stdout contamination breaking DSC JSON parsing * Fix Copilot remark
1 parent 2d2a504 commit 71cf1e3

2 files changed

Lines changed: 46 additions & 4 deletions

File tree

‎src/dsc/psresourceget.ps1‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,11 @@ function SetPSResourceList {
586586
if ($resourcesToUninstall.Count -gt 0) {
587587
Write-Trace -message "Uninstalling resources: $($resourcesToUninstall | ForEach-Object { "$($_.Name) - $($_.Version)" })" -level debug
588588
$resourcesToUninstall | ForEach-Object {
589-
Uninstall-PSResource -Name $_.Name -Scope $scope -ErrorAction Stop
589+
$cmdWarnings = $null
590+
Uninstall-PSResource -Name $_.Name -Scope $scope -ErrorAction Stop -WarningVariable cmdWarnings
591+
foreach ($w in $cmdWarnings) {
592+
Write-Trace -message ([string]$w) -level warn
593+
}
590594
}
591595
$resourcesChanged = $true
592596
}
@@ -614,9 +618,12 @@ function SetPSResourceList {
614618
$version = $_.Version
615619

616620
try {
617-
Install-PSResource -Name $_.Name -Version $_.Version -Scope $scope -Repository $repositoryName -ErrorAction Stop -TrustRepository:$inputObj.trustedRepository -Prerelease:$usePrerelease -Reinstall
618-
}
619-
catch {
621+
$cmdWarnings = $null
622+
Install-PSResource -Name $_.Name -Version $_.Version -Scope $scope -Repository $repositoryName -ErrorAction Stop -TrustRepository:$inputObj.trustedRepository -Prerelease:$usePrerelease -Reinstall -WarningVariable cmdWarnings
623+
foreach ($w in $cmdWarnings) {
624+
Write-Trace -message ([string]$w) -level warn
625+
}
626+
} catch {
620627
Write-Trace -level error -message "Failed to install resource '$name' with version '$version'. Error: $($_.Exception.Message)"
621628
$installErrors += $_.Exception.Message
622629
}
@@ -825,6 +832,10 @@ if ($null -eq (Get-Module -Name Microsoft.PowerShell.PSResourceGet)) {
825832
Import-Module -Name $path -Force -ErrorAction Stop
826833
}
827834

835+
# Suppress warnings from PSResourceGet cmdlets to prevent them from reaching stdout and
836+
# breaking DSC's JSON parsing. Warnings should be captured on individual cmdlets
837+
$WarningPreference = 'SilentlyContinue'
838+
828839
switch ($Operation.ToLower()) {
829840
'get' { return (GetOperation -ResourceType $ResourceType) }
830841
'set' { return (SetOperation -ResourceType $ResourceType) }

‎test/DscResource/PSResourceGetDSCResource.Tests.ps1‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,37 @@ Describe "PSResourceList Resource Tests" -Tags 'CI' {
243243
$setResult.afterState.resources[1].version | Should -Be '5.0.0'
244244
}
245245

246+
It 'Set operation stdout contains only valid JSON and is not contaminated by warning messages' {
247+
# Simple regression test as it is hard to predict a warning message but we want to ensure they do not break DSC's JSON parsing. This test does not verify that warnings are emitted when expected,
248+
# only that if they are emitted they do not reach stdout.
249+
Uninstall-PSResource -Name $script:testModuleName -ErrorAction SilentlyContinue
250+
251+
$psResourceListParams = @{
252+
repositoryName = $script:localRepo
253+
trustedRepository = $true
254+
resources = @(
255+
@{
256+
name = $script:testModuleName
257+
version = '1.0.0'
258+
}
259+
)
260+
}
261+
262+
$resourceInput = $psResourceListParams | ConvertTo-Json -Depth 5
263+
264+
# Capture only stdout; stderr carries DSC trace messages and is intentionally discarded
265+
$stdoutLines = & $script:dscExe resource set --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $resourceInput -o json 2>$null
266+
267+
# No stdout line should contain warning text or ANSI escape sequences
268+
$stdoutLines | Where-Object { $_ } | ForEach-Object {
269+
$_ | Should -Not -Match 'WARNING:'
270+
$_ | Should -Not -Match '\x1b\['
271+
}
272+
273+
# stdout must be parseable as JSON without error
274+
{ $stdoutLines | ConvertFrom-Json -ErrorAction Stop } | Should -Not -Throw
275+
}
276+
246277
It 'Can test a PSResourceList resource instance with resources' {
247278
$psResourceListParams = @{
248279
repositoryName = $script:localRepo

0 commit comments

Comments
 (0)