Note: Splatting only works reliably with PowerShell commands, because the way PowerShell translates it for external programs, as shown in Mathias' answer, is not a format that most external programs understand.
As Mathias points out in a comment on the question, you cannot directly get a splatting invocation's equivalent expressed as individual arguments.
However, you can use the Trace-Command
cmdlet to trace parameter binding, IF you have a command (represented by $yourCommand
below) that actually accepts the parameters specified in the hashtable:
Trace-Command -pshost -name ParameterBinding { & $yourCommand @params }
Note: Trace-Command
's output is verbose and technical; interpreting it takes some practice.
Your desire to capture the equivalent of a splatting-based invocation in a command-line string is impossible to achieve in all cases, given the object-based nature of PowerShell: not all objects can be represented faithfully as strings.
That said, if you know that the arguments being passed are limited to strings, numbers, and switches, you can do the following:
# Sample hashtable used for splatting, limited to strings, numbers, switches.
$somePath = 'C:\test\path'
$params = [ordered] @{
Path = "$SomePath" # string
Count = 42 # number
Skip = $True # [switch] parameter, expressed as a [bool] value in splatting
}
# Translate the hashtable into an equivalent command-line string.
$params.GetEnumerator().ForEach({
$val = $_.Value
if ($val -is [string]) { $val = "'{0}'" -f $val.Replace("'", "''") }
'-{0}:{1}' -f $_.Key, $val
}) -join ' '
The above yields a string with the following content:
-Path:'C:\test\path' -Count:42 -Skip:True
Prepending the command name to the string resulting from the above would give you a string representation of a complete command.
That string representation could be saved to a script file, for instance.
If you wanted to execute the string containing the command-line directly, you'd have to resort to Invoke-Expression
, because &
, the call operator, does not operate on entire command lines, only on the names/paths of commands specified via a variable, quoted string, or expression.
The obligatory warning about Invoke-Expression
:
Invoke-Expression
should generally be avoided and used only as a last resort, due to its inherent security risks. In short: Avoid it, if possible, given that superior alternatives are usually available. If there truly is no alternative, only ever use it on input you either provided yourself or fully trust - see this answer.
In general, if possible, use PowerShell's own, fully object-aware way of defining snippets of code to be executed on demand later, namely script blocks ({ ... }
).