I am trying to create a PowerShell script, and one of the parameters of the script is a Hashtable. I am using PowerShell 7.2 for this project, and whenever I try to pass a Hashtable in through the command line, it passes it as the string System.Collections.Hashtable
instead of the Hashtable itself. This causes the script to throw an error as the parameter is types as a Hashtable.
Here is a shortened version of the script I have written.
#requires -version 7.2
[CmdletBinding(PositionalBinding = $False)]
param ([hashtable] $TestTable)
$TestTable
I have tried the following command in the PowerShell command line.
pwsh .\ScriptName.ps1 -TestTable @{Test = "This is a test"}
pwsh -Command .\ScriptName.ps1 -TestTable @{Test = "This is a test"}
And many variants of these attempting different combinations of commas, quotes, brackets, and @ symbols.
When I run either of the two commands listed above I get the error ScriptName.ps1: Cannot process argument transformation on parameter 'TestTable'. Cannot convert the "System.Collections.Hashtable" value of type "System.String" to type "System.Collections.Hashtable".
I am trying to stick with PowerShell 7.2 for the project. When I remove the requirement for 7.2 and run the command without pwsh, it works perfectly, but I have not been able to find a solution that works for 7.2. If anyone knows how to do this, I would greatly appreciate an explanation.
I have tried the following command in the PowerShell command line.
There's usually no good reason to call pwsh
, the PowerShell (Core) CLI, from PowerShell, given that you can invoke .ps1
files directly, in-process:
.\ScriptName.ps1 -TestTable @{Test = "This is a test"}
If you want to call via the CLI nonetheless (e.g. to confine to a child process any session-level changes a (potentially ill-behaved) script may make), use a script block ({ ... }
) for your invocation:
pwsh { .\ScriptName.ps1 -TestTable @{Test = "This is a test"} }
Note:
Passing a script block only works from inside PowerShell,
There, its use implies the -Command
(-c
) CLI parameter
-Command
(-c
) is required, because -File
is the default in PowerShell (Core) 7+ (unlike in Windows PowerShell).If you want to pass arguments to the script block (usually based on the caller's values), follow the script-block argument with an --args
argument that is an array of positional arguments that the script block should see, by default via the automatic $args
variable; e.g.:
pwsh { "$($args.Count) args received."; $args } -args foo, bar
Calling from outside PowerShell requires that you comply with the syntax requirements of the calling shell in order to pass the "
chars. that are part of the PowerShell command to executed through:
From cmd.exe
(Windows)
pwsh -Command ".\ScriptName.ps1 -TestTable @{Test = \"This is a test\"}"
From POSIX-compatible shells such as Bash (on Unix-like platforms):
pwsh -Command '.\ScriptName.ps1 -TestTable @{Test = "This is a test"}'
"...\"...\"..."
approach would work as well in principle, commands containing $
chars. would require those to be \
-escaped as well in order to be passed through. On the plus side, not escaping them allows you to embed variable values from the caller in the command (the equivalent approach from cmd.exe
on Windows would be to use %...%
variable references).As for what output a caller to PowerShell's CLI receives:
When calling from inside PowerShell using a script block:
Otherwise (when calling from outside PowerShell / using a string to pass the command):
All outputs are strings (text), using the character encoding implied by the console window's code page (as reflected in [Console]::OutputEncoding
inside PowerShell).
Complex objects - e.g. the System.IO.FileSystemInfo
that Get-ChildItem
outputs - are represented by their for-display string representations, as they would print to the display from inside an interactive PowerShell session.
The only way to produce structured text output is to pass -OutputFormat xml
(-of xml
), which results in CLIXML output, i.e the XLM-based format that PowerShell itself uses for cross-process serialization; however, outside of PowerShell there aren't any well-known libraries that can consume this format.