From 2b18a248a3bc71a48868ec5e25730063d302861a Mon Sep 17 00:00:00 2001 From: "G.Reijn" <26114636+Gijsreyn@users.noreply.github.com> Date: Sat, 23 May 2026 13:06:43 +0200 Subject: [PATCH 1/2] fix: capture cmdlet warnings to prevent stdout contamination breaking DSC JSON parsing --- src/dsc/psresourceget.ps1 | 19 +++++++++--- .../PSResourceGetDSCResource.Tests.ps1 | 31 +++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/dsc/psresourceget.ps1 b/src/dsc/psresourceget.ps1 index f6f9eb50d..f26a2b4c2 100644 --- a/src/dsc/psresourceget.ps1 +++ b/src/dsc/psresourceget.ps1 @@ -586,7 +586,11 @@ function SetPSResourceList { if ($resourcesToUninstall.Count -gt 0) { Write-Trace -message "Uninstalling resources: $($resourcesToUninstall | ForEach-Object { "$($_.Name) - $($_.Version)" })" -level debug $resourcesToUninstall | ForEach-Object { - Uninstall-PSResource -Name $_.Name -Scope $scope -ErrorAction Stop + $cmdWarnings = $null + Uninstall-PSResource -Name $_.Name -Scope $scope -ErrorAction Stop -WarningVariable cmdWarnings + foreach ($w in $cmdWarnings) { + Write-Trace -message $w.Message -level warn + } } $resourcesChanged = $true } @@ -614,9 +618,12 @@ function SetPSResourceList { $version = $_.Version try { - Install-PSResource -Name $_.Name -Version $_.Version -Scope $scope -Repository $repositoryName -ErrorAction Stop -TrustRepository:$inputObj.trustedRepository -Prerelease:$usePrerelease -Reinstall - } - catch { + $cmdWarnings = $null + Install-PSResource -Name $_.Name -Version $_.Version -Scope $scope -Repository $repositoryName -ErrorAction Stop -TrustRepository:$inputObj.trustedRepository -Prerelease:$usePrerelease -Reinstall -WarningVariable cmdWarnings + foreach ($w in $cmdWarnings) { + Write-Trace -message $w.Message -level warn + } + } catch { Write-Trace -level error -message "Failed to install resource '$name' with version '$version'. Error: $($_.Exception.Message)" $installErrors += $_.Exception.Message } @@ -825,6 +832,10 @@ if ($null -eq (Get-Module -Name Microsoft.PowerShell.PSResourceGet)) { Import-Module -Name $path -Force -ErrorAction Stop } +# Suppress warnings from PSResourceGet cmdlets to prevent them from reaching stdout and +# breaking DSC's JSON parsing. Warnings should be captured on individual cmdlets +$WarningPreference = 'SilentlyContinue' + switch ($Operation.ToLower()) { 'get' { return (GetOperation -ResourceType $ResourceType) } 'set' { return (SetOperation -ResourceType $ResourceType) } diff --git a/test/DscResource/PSResourceGetDSCResource.Tests.ps1 b/test/DscResource/PSResourceGetDSCResource.Tests.ps1 index ce320dc62..f6fcf150f 100644 --- a/test/DscResource/PSResourceGetDSCResource.Tests.ps1 +++ b/test/DscResource/PSResourceGetDSCResource.Tests.ps1 @@ -243,6 +243,37 @@ Describe "PSResourceList Resource Tests" -Tags 'CI' { $setResult.afterState.resources[1].version | Should -Be '5.0.0' } + It 'Set operation stdout contains only valid JSON and is not contaminated by warning messages' { + # 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, + # only that if they are emitted they do not reach stdout. + Uninstall-PSResource -Name $script:testModuleName -ErrorAction SilentlyContinue + + $psResourceListParams = @{ + repositoryName = $script:localRepo + trustedRepository = $true + resources = @( + @{ + name = $script:testModuleName + version = '1.0.0' + } + ) + } + + $resourceInput = $psResourceListParams | ConvertTo-Json -Depth 5 + + # Capture only stdout; stderr carries DSC trace messages and is intentionally discarded + $stdoutLines = & $script:dscExe resource set --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $resourceInput -o json 2>$null + + # No stdout line should contain warning text or ANSI escape sequences + $stdoutLines | Where-Object { $_ } | ForEach-Object { + $_ | Should -Not -Match 'WARNING:' + $_ | Should -Not -Match '\x1b\[' + } + + # stdout must be parseable as JSON without error + { $stdoutLines | ConvertFrom-Json -ErrorAction Stop } | Should -Not -Throw + } + It 'Can test a PSResourceList resource instance with resources' { $psResourceListParams = @{ repositoryName = $script:localRepo From 511fb360e66d89a9437006142cc370c000bc4838 Mon Sep 17 00:00:00 2001 From: "G.Reijn" <26114636+Gijsreyn@users.noreply.github.com> Date: Sat, 23 May 2026 13:13:13 +0200 Subject: [PATCH 2/2] Fix Copilot remark --- src/dsc/psresourceget.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dsc/psresourceget.ps1 b/src/dsc/psresourceget.ps1 index f26a2b4c2..ea452d522 100644 --- a/src/dsc/psresourceget.ps1 +++ b/src/dsc/psresourceget.ps1 @@ -589,7 +589,7 @@ function SetPSResourceList { $cmdWarnings = $null Uninstall-PSResource -Name $_.Name -Scope $scope -ErrorAction Stop -WarningVariable cmdWarnings foreach ($w in $cmdWarnings) { - Write-Trace -message $w.Message -level warn + Write-Trace -message ([string]$w) -level warn } } $resourcesChanged = $true @@ -621,7 +621,7 @@ function SetPSResourceList { $cmdWarnings = $null Install-PSResource -Name $_.Name -Version $_.Version -Scope $scope -Repository $repositoryName -ErrorAction Stop -TrustRepository:$inputObj.trustedRepository -Prerelease:$usePrerelease -Reinstall -WarningVariable cmdWarnings foreach ($w in $cmdWarnings) { - Write-Trace -message $w.Message -level warn + Write-Trace -message ([string]$w) -level warn } } catch { Write-Trace -level error -message "Failed to install resource '$name' with version '$version'. Error: $($_.Exception.Message)"