1

I'm running C# PowerShell code on a remote system and need to get the value of a local variable. PowerShell has a cmdlet named Get-Variable which I'm trying to use. This is my code for trying to fetch the relevant collection of PSVariables (which obviously should contain just one):

psShell.AddScript($"$text = 'someValue'");

psShell.Invoke();

psShell.Commands.Clear();

psShell.AddCommand("Get-Variable")
.AddParameter("Name", "text");

var v = psShell.Invoke<PSVariable>();

Problem is on the last line, I get the following exception:

Cannot convert the "System.Management.Automation.PSVariable" value of type "Deserialized.System.Management.Automation.PSVariable" to type "System.Management.Automation.PSVariable".

Anyone know how to solve this ?

Also, I know of the SessionStateProxy method mentioned on StackOverflow, but as this post of mine shows, it doesn't work for my scenario for some reason.

Ahmad
  • 12,886
  • 30
  • 93
  • 146
  • I can't reproduce this in PowerShell. I get the variable returned using a generic method. Have you tried setting `var v` to `System.Collections.ObjectModel.Collection`? See [Invoke()](https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.powershell.invoke?view=pscore-6.2.0#System_Management_Automation_PowerShell_Invoke__1) – Ash May 06 '20 at 00:15
  • I meant changing `var` to `System.Collections.ObjectModel.Collection`. – Ash May 06 '20 at 00:23
  • 1
    While I haven't tried it, it should not help because using `var` automatically infers the correct data type .. that is it's own point! – Ahmad May 06 '20 at 02:20
  • I'm aware, I just wanted to to see if something strange was going on and declaring the object explicitly worked. You have an answer anyway. – Ash May 06 '20 at 08:15

1 Answers1

2

When PowerShell remoting is involved, only a handful of well-known types deserialize with type fidelity, System.Management.Automation.PSVariable not being among them.

Instances of all other types deserialize as method-less emulations of the original objects, as [psobject] instances with properties containing static copies of the original property values.
In PowerShell, these instances report their type name as the original type name prefixed with Deserialized.
See this answer for background information.

The simplest way to handle such objects is via the DLR:

dynamic v = psShell.Invoke();

Then you can access properties as usual (albeit with runtime binding), e.g., v.Name.

mklement0
  • 382,024
  • 64
  • 607
  • 775