How to save complex PowerShell variables as CliXML instead of Newtonsoft.Json.Linq.JProperty in the Azure Automation
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
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:
How you can retrieve it in your runbook: