How to save complex PowerShell variables as CliXML instead of Newtonsoft.Json.Linq.JProperty in the Azure Automation

Nov 29, 2022ยท

3 min read

Play this article

Azure Automation Account has a handy feature to define (shared) Variables that can be used across all your Runbooks. What is not so nice at least for me was finding that complex objects like a hashtable, arrays, psobjects, etc are stored as Newtonsoft.Json.Linq.JProperty image.png

This makes retrieving the content of the variables quite unfriendly if you are not familiar with this Newtonsoft.Json.Linq.JProperty.

Solution

How to "solve" this? Save variables using old good Export-CliXML and then retrieve them using Import-CliXML ๐Ÿ˜‰. If you do so, nothing will change for you when you try to work with the saved variable. The array will be still array, psobject will be still psobject etc. But beware that you have to save the output of Export-CliXML as a string! Otherwise Azure will again use Newtonsoft.Json.Linq.JProperty to save the variable.

I've created two proxy functions for the export/import of the variables using CliXML commands. And because the built-in functions are named Set-AutomationVariable and Get-AutomationVariable, I've just put the suffix '2' to them (that's my probably weird habit ๐Ÿ˜‹).

function Set-AutomationVariable2 {
    <#
    .SYNOPSIS
    Function for setting Azure RunBook variable value by exporting given value using Export-CliXml and saving the text result.

    .DESCRIPTION
    Function for setting Azure RunBook variable value by exporting given value using Export-CliXml and saving the text result.
    Compared to original Set-AutomationVariable this one is able to save original PSObjects as they were and not as Newtonsoft.Json.Linq.
    Variable set using this function has to be read using Get-AutomationVariable2!

    As original Set-AutomationVariable can be used only inside RunBook!

    .PARAMETER name
    Name of the RunBook variable you want to set.

    (to later retrieve such variable, use Get-AutomationVariable2!)

    .PARAMETER value
    Value you want to export to RunBook variable.
    Can be of any type.

    .EXAMPLE
    Set-AutomationVariable2 -name myVar -value @{name = 'John'; surname = 'Doe'}

    # to retrieve the variable
    #$hashTable = Get-AutomationVariable2 -name myVar

    Save given hashtable to variable myVar.

    .NOTES
    As original Set-AutomationVariable can be used only inside RunBook!
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string] $name,

        $value
    )

    if ($value) {
        $cliXmlFile = New-TemporaryFile
        $value | Export-Clixml $CliXmlFile.FullName
        $processedValue = [string](Get-Content $cliXmlFile.FullName -Raw)
    } else {
        $processedValue = ''
    }

    Set-AutomationVariable -Name $name -Value $processedValue
}
function Get-AutomationVariable2 {
    <#
    .SYNOPSIS
    Function for getting Azure RunBook variable exported using Set-AutomationVariable2 function (a.k.a. using Export-CliXml).

    .DESCRIPTION
    Function for getting Azure RunBook variable exported using Set-AutomationVariable2 function (a.k.a. using Export-CliXml).
    Compared to original Get-AutomationVariable this one is able to get original PSObjects as they were and not as Newtonsoft.Json.Linq.

    As original Get-AutomationVariable can be used only inside RunBook!

    .PARAMETER name
    Name of the RunBook variable you want to retrieve.

    (such variable had to be set using Set-AutomationVariable2!)

    .EXAMPLE
    # save given hashtable to variable myVar
    #Set-AutomationVariable2 -name myVar -value @{name = 'John'; surname = 'Doe'}

    Get-AutomationVariable2 myVar

    Get variable myVar.

    .NOTES
    As original Get-AutomationVariable can be used only inside RunBook!
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string] $name
    )

    try {
        $xml = Get-AutomationVariable -Name $name -ErrorAction Stop
    } catch {
        Write-Error $_
        return
    }

    if ($xml) {
        $cliXmlFile = New-TemporaryFile
        Set-Content -Path $cliXmlFile.FullName -Value $xml
        Import-Clixml $cliXmlFile
    } else {
        return
    }
}

How the variable will look like: image.png

How you can retrieve it in your runbook: image.png

Did you find this article valuable?

Support Ondrej Sebela by becoming a sponsor. Any amount is appreciated!

ย