When defining "private global" variables to be used with functions and scripts in JEA sessions using New-PSSessionConfigurationFile, I noticed that I'm only able to create string variables.

Is there any way to define other types of objects in the VariableDefinitions section?

The following definitions

VariableDefinitions @(
  @{ Name = 'Test'   ; Value = 'blah' }
  @{ Name = 'Integer'; Value = 13 }
  @{ Name = 'Array'  ; Value = @(1,2,3,4,'b') }

  @{
    Name  = 'Hash'
    Value = @{
      Hash1 = '1'
      Hash2 = '2'
    }
  }

)

will result in (if allowing Invoke-Command in Visible Cmdlets of course)

> Invoke-Command {$Test}
blah

> Invoke-Command {$Integer}
13

> Invoke-Command {$Array}
System.Object[]

> Invoke-Command {$Hash}
System.Collections.Hashtable

At first, I got confused, as the result indicated some kind of object was returned. But on closer inspection, it turned out to be the original object type name that was returned as a string.

> Invoke-Command {$Array -is [string]}
True

> Invoke-Command {$Hash -is [string]}
True

> Invoke-Command {$Integer -is [string]}
True

So it would seem that the only objects possible to define using VariableDefinitions is variables of type [string].

But is there a way of defining other types of variables using VariableDefinitions?

2

There are 2 best solutions below

0
Dennis On BEST ANSWER

Ok, here's a no-brainer spotted by a colleague of mine. Why not just use JSON-notation for the parts that isn't strings?

This will still require some work on the receiving end, but far less as specified in my previous suggestion.

VariableDefinitions @(
  @{ Name = 'Test'   ; Value = 'blah' }

  @{
    Name  = 'TestHash'
    Value = '{
      "Hash1" : "1"
      "Hash2" : "2"
    }'
  }

)

Accessing the variables will result in

> Invoke-Command {$Test}
blah

> Invoke-Command {$TestHash}
{
  "Hash2" : "2"
  "Hash1" : "1"
}

This can of course be converted to PowerShell dataformat using ConvertFrom-Json, with one little caveat.

> Invoke-Command {$TestHash | ConvertFrom-Json}

Hash2 Hash1
----- -----
2     1

To bring it back to a hash value we need to use ConvertFrom-Json -AsHashTable. And if using Windows PowerShell 5.1, this can be accomplished with

> Invoke-Command {
  Add-Type -AssemblyName System.Web.Extensions # Might not be needed
  $Parser = New-Object Web.Script.Serialization.JavaScriptSerializer

  $Parser.Deserialize($TestHash, [hashtable])
}

Name            Value
----            -----
Hash1           1
Hash2           2

See Create Hashtable from JSON

0
Dennis On

A workaround for not being able to define hash variables in VariableDefintions, might be to define all the key pairs as separate string variables and then construct the hash variable in each function/script where it is to be used...

I don't fancy this solution, but it's doable.

1. Define the simple variables

VariableDefinitions @(
  @{ Name = 'Cars1'   ; Value = 'MyCar'   }
  @{ Name = 'Cars1Val'; Value = 'Volvo'   }

  @{ Name = 'Cars2'   ; Value = 'YourCar' }
  @{ Name = 'Cars2Val'; Value = 'Tesla'   }
}

2. Define the helper function in all placec needed

This helper function will make it somewhat easier to use hash variables.
Do NOT place it as a standalone function in FunctionDefinitions as that would expose the feature to the JEA-user.

function New-HashVariable {
<#
.NOTES
  Looks for simple string variables already defined in pairs, like

  $VarNameX - $VarNameXVal
  $VarNameY - $VarNameYVal

  and creates a hashtable, $VarName, containing the labeled
  values provided in the simple string variables.
#>

  [CmdletBinding()]
  param (
    [string]$Name,
    [switch]$ValueOnly
  )

  Set-Variable $Name -Value @{} -Force
  $KeyIndex = 0

  Get-Variable -Name "$($Name)?" -ValueOnly | foreach {#hash value pair found
    $KeyIndex++

    Set-Variable $Name -Value (#add a value pair
      (Get-Variable $Name -ValueOnly) + @{
        (Get-Variable -Name "$($Name)$KeyIndex" -ValueOnly) =
        (Get-Variable -Name "$($Name)$($KeyIndex)Val" -ValueOnly)
      }
    )#end extend hash table

  }#end foreach value pair

  if ($ValueOnly) {
    return Get-Variable $Name -ValueOnly
  }

  return Get-Variable $Name

}

3. Create the hash variable wherever needed...

Invoke-Command {
  <define helper function>

  $Cars = New-HashVariable 'Cars' -ValueOnly
}

Adding $cars at the end of the Invoke-Command will result in

> $cars

Name      Value
----      -----
YourCar   Tesla
MyCar     Volvo

You could of course declare the hash variables normally in any script defined in ScriptsToProcess, but that won't keep the hash values hidden.

The same goes for using New-HashVariable in a script. In that case you'd need to delete it after usage in the script or else it will be available in the JEA interactive console session.