Home > front end >  Generate CLIXML string from a PowerShell object without serializing to disk first
Generate CLIXML string from a PowerShell object without serializing to disk first

Time:12-31

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:

  1. 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;

  2. 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 and Import-CliXml cmdlets - in the form of new ConvertTo-CliXml and ConvertFrom-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 of 1, whereas Export-CliXml defaults to 2; use the overload that allows specifying the recusion depth explicitly, if needed (e.g., [System.Management.Automation.PSSerializer]::Serialize($Person, 2))

  • Related