Liam Matthews
Liam Matthews

Reputation: 43

PowerShell Hashtable not returning correctly

I am sure I have had this working before with no issues but now I am not sure what is going on.

Script1.ps1:

$Output = PowerShell.exe -File "C:\Temp1\Script2.ps1"
$Output.Value1

Script2.ps1:

$HashTable = New-Object PSObject -Property @{
    "Value1" = "Data1"
    "Value2" = "Data2"
    "Value3" = "Data3"
}
return $HashTable

I was expecting to get a clean table that I could pull data from but instead I get this:

screenshot

If I just run Script2 on it's own I can use $HashTable.Value1 but returning it to Script1 seems to be an issue.

Upvotes: 1

Views: 4013

Answers (3)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200203

You're running Script2.ps1 in a different PowerShell process. PowerShell objects like hashtables are not transported across process boundaries. Instead the output is transformed into an array of strings.

Demonstration:

PS C:\> $Output = powershell.exe -File '.\test.ps1'
PS C:\> $Output

Value1              Value2              Value3
------              ------              ------
Data1               Data2               Data3


PS C:\> $Output.GetType().FullName
System.Object[]
PS C:\> $Output[0].GetType().FullName
System.String
PS C:\> $Output | % { '=' + $_.Trim() + '=' }
==
=Value1              Value2              Value3=
=------              ------              ------=
=Data1               Data2               Data3=
==
==

Run the script in the current PowerShell process (e.g. via the call operator) to avoid this:

PS C:\> $Output = & '.\test.ps1'
PS C:\> $Output

Value1              Value2              Value3
------              ------              ------
Data1               Data2               Data3


PS C:\> $Output.GetType().FullName
System.Management.Automation.PSCustomObject
PS C:\> $Output.Value1
Data1

Side note: as @sodawillow pointed out in the comments to your question you're creating a custom object, not a hashtable.

Upvotes: 2

Simon Catlin
Simon Catlin

Reputation: 2229

Agree with sodawillow; just use:

[Hashtable] $HashTable = @{ 'Value1' = 'Data1';
                            'Value2' = 'Data2';
                            'Value3' = 'Data3'
                          }
return $HashTable;

Upvotes: 1

BartekB
BartekB

Reputation: 8650

When you are running PowerShell.exe - you are effectively calling external command, and result you get is most likely [System.Object[]]. You can verify it easily using method GetType:

$Output.GetType()

The way you should run PowerShell scripts is either call operator (&) or dot-sourcing operator (.). Former will run a script in it's own scope (so variables/functions defined in the script won't "leak" into the parent scope). Latter will execute script as if it was integral part of the parent. In your case call operator should do what you need:

$Output = & "c:\temp\Script1.ps1"
# or - as there are no spaces in the path, so script acts as any other command...
$Output = c:\temp\Script1.ps1

That should give you custom object, as expected. To get just hashtable - you don't need New-Object - just return hash table passed to Property parameter of that command.

Upvotes: 3

Related Questions