Avoid decorating ErrorRecord during CliXml serialization#27528
Avoid decorating ErrorRecord during CliXml serialization#27528KirtiRamchandani wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR prevents Export-Clixml / ConvertTo-CliXml remoting serialization from mutating the input ErrorRecord (and InformationalRecord) by adding remoting-only members to the original object, and adds regression coverage for ErrorRecord.
Changes:
- Add Pester tests asserting
ErrorRecorddoes not gain new extended members after CliXml serialization. - Update serialization logic to serialize a remoting-only wrapper
PSObjectinstead of mutating the originalPSObjectforErrorRecord/InformationalRecord.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| test/powershell/Modules/Microsoft.PowerShell.Utility/clixml.tests.ps1 | Adds regression tests and a helper to compare extended member sets pre/post serialization. |
| src/System.Management.Automation/engine/serialization.cs | Introduces a wrapper-copy strategy for remoting serialization to avoid persisting remoting-only members on the source object. |
| $filePath = Join-Path $subFilePath 'error.xml' | ||
| Write-Error foo 2>$null | ||
| $errorRecord = $Error[0] | ||
| $before = Get-ExtendedMemberName $errorRecord |
There was a problem hiding this comment.
Addressed in 16245c451: the Export-Clixml test now captures the produced ErrorRecord directly through New-TestErrorRecord instead of reading $Error[0].
| Write-Error foo 2>$null | ||
| $errorRecord = $Error[0] | ||
| $before = Get-ExtendedMemberName $errorRecord |
There was a problem hiding this comment.
Addressed in 16245c451: the ConvertTo-CliXml test now uses the same deterministic ErrorRecord capture helper instead of depending on global error state.
| function Get-ExtendedMemberName { | ||
| param([object] $InputObject) | ||
|
|
||
| @($InputObject | Get-Member -View Extended | Select-Object -ExpandProperty Name) | ||
| } |
There was a problem hiding this comment.
Addressed in 16245c451: the helper is now named Get-ExtendedMemberNames to match its collection result.
| foreach (PSMemberInfo member in source.InstanceMembers) | ||
| { | ||
| if (!member.IsHidden) | ||
| { | ||
| target.Members.Add(member); | ||
| } | ||
| } |
There was a problem hiding this comment.
Addressed in 16245c451: the remoting serialization wrapper now adds member.Copy() to target.InstanceMembers, so the wrapper owns independent member instances.
| InformationalRecord informationalRecord = mshSource.ImmediateBaseObject as InformationalRecord; | ||
| if (informationalRecord != null) | ||
| { | ||
| mshSource = GetRemotingSerializationTarget(mshSource); | ||
| informationalRecord.ToPSObjectForRemoting(mshSource); | ||
| isInformationalRecord = true; | ||
| break; |
There was a problem hiding this comment.
Addressed in 16245c451: added matching Export-Clixml and ConvertTo-CliXml regression coverage for InformationRecord inputs.
PR Summary
Fixes #25854.
ConvertTo-CliXmlandExport-CliXmlserializeErrorRecordinstances by adding remoting-specific note properties such asErrorCategory_ActivityandInvocationInfo. The serializer was adding those properties to the caller'sPSObjectwrapper, which caused the originalErrorRecordto gain serialization-only extended members after serialization completed.This change serializes remoting records through a wrapper with local instance members, preserving the generated CliXml fields without decorating the caller's input object.
PR Context
PSObject.Copy()alone still shares the base object's resurrection-table key, so note properties added to the copy are visible on wrappers around the same base object. The new helper resets the serialization wrapper's instance-member collection before adding remoting-only properties, while preserving existing visible instance members for serialization.The same path is used for informational records, so the isolation is applied there too.
PR Checklist
Tests
ErrorRecordincreased extended members from 1 to 13 and addedErrorCategory_*,InvocationInfo,SerializeExtendedInfo, and related serialization notes.Export-ClixmlandConvertTo-CliXml.Start-PSBuild -Configuration Debug -SMAOnlyConvertTo-CliXmlandExport-Clixmladded no extended members to the originalErrorRecord.ErrorCategory_CategoryandConvertFrom-CliXmlround-trips the error information.Start-PSPester -Path .\test\powershell\Modules\Microsoft.PowerShell.Utility\clixml.tests.ps1 -Terse -ThrowOnFailure -SkipTestToolBuild -BinDir <publish>(19 passed)git diff --check(line-ending warning only)