I have the following code which exports an object to an XML file, then reads it back in and prints it on the Information stream.
try{
# Sample object
$Person = @{
Name = 'Bender'
Age = 'At least 1074'
}
$Person | Export-CliXml obj.xml
$cliXml = Get-Content -Raw ./obj.xml
Write-Host $cliXml
} finally {
if( Test-Path ./obj.xml ) {
Remove-Item -Force ./obj.xml -EV rError -EA SilentlyContinue
if( $rError ) {
Write-Warning "Failed to remove ./obj.xml: $($rError.Exception.Message)"
}
Remove-Variable -Force $rError -EA Continue
}
}
There is a system-local parent session which watches its STDOUT for this output and reconstructs it to an object in its own session.
NOTE: I know a local PSRemoting session would work, but I need this to also work on systems which PSRemoting has either not yet been configured or will not be.
I'd like to cut out the middleman and instead of writing the object to disk. Unfortunately,Import-CliXMl
and Export-CliXml
are the only cmdlets with CliXml
in the name, and doing some .NET documentation sleuthing has turned up nothing so far.
Is there a way to simply serialize an object to a CliXml string without writing to disk first? I've considered using $Person | ConvertTo-Json -Compress -Depth 100
but this has two issues:
Only captures nested objects up to 100 levels deep. This is an edge case but still a limit I'd like to avoid. I could always use another library or another format, but;
I want these to be reconstructed into .NET objects of the same type they were before serialization. Recreating objects with CliXml is the only way I'm aware of that this can be done.
CodePudding user response:
The CliXml serializer is exposed via the [PSSerializer]
class:
$Person = @{
Name = 'Bender'
Age = 'At least 1074'
}
# produces the same XML ouput as `Export-CliXml $Person`
[System.Management.Automation.PSSerializer]::Serialize($Person)
To deserialize CliXml, use the Deserialize
method:
$cliXml = [System.Management.Automation.PSSerializer]::Serialize($Person)
$deserializedPerson = [System.Management.Automation.PSSerializer]::Deserialize($cliXml)
CodePudding user response:
To complement Mathias' helpful answer:
Introducing in-memory equivalents to the file-based
Export-CliXml
andImport-CliXml
cmdlets - in the form of newConvertTo-CliXml
andConvertFrom-CliXml
cmdlets - has been green-lighted in principle, but is still awaiting implementation by the community (as of PowerShell 7.2.1) - see GitHub issue #3898.Note that
[System.Management.Automation.PSSerializer]::Serialize()
defaults to a recursion depth of1
, whereasExport-CliXml
defaults to2
; use the overload that allows specifying the recusion depth explicitly, if needed (e.g.,[System.Management.Automation.PSSerializer]::Serialize($Person, 2)
)