powershellpowershell-remotingremotingjea

How do I define hash tables with protected values using the VariableDefinitions section in PowerShell JEA session configuration files?


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?


Solution

  • 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