Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splatting a hashtable - Start-Process -ArgumentList

Tags:

powershell

I'm trying to install an .MSI using splatting:

$InstallerArgs @{
    "DATABASENAME" = "my_database";
    "LOCALIP" = "127.0.0.1";
    "USERNAME" = "username1";
    "/i" = "C:\Files\Installer.msi";
}

I then call Start-Process:

Start-Process -FilePath msiexec.exe -ArgumentList @InstallerArgs -Wait

This returns the error: Missing an argument for parameter 'ArgumentList'. Specify a parameter of type 'System.String[]' and try again.

Is it not possible to use splatting with Start-Process?

like image 617
LightningWar Avatar asked Apr 18 '26 15:04

LightningWar


1 Answers

Splatting (@<varName>) isn't supported as a parameter value (argument); instead, the hashtable that is splatted itself represents a set of parameter name-value pairs.

Olaf's helpful answer, by contrast, demonstrates proper use of splatting, where the hashtable contains the parameter name-value pairs for Start-Process as a whole, with the pass-through-to-msiexec parameters specified as an array in the ArgumentList hashtable entry.

If you do want to maintain just the pass-through-to-msiexec arguments in a separate data structure, use an array and pass it as such, given that -ArgumentList indeed expects a string array as its argument ([string[]]):

$InstallerArgs = @(
    "DATABASENAME=my_database"
    "LOCALIP=127.0.0.1"
    "USERNAME=username1"
    "/i"
    "C:\Files\Installer.msi"
)

# Note: NO splatting
Start-Process -FilePath msiexec.exe -ArgumentList $InstallerArgs -Wait

The above ends up executing the following:

msiexec.exe DATABASENAME=my_database LOCALIP=127.0.0.1 USERNAME=username1 /i C:\Files\Installer.msi

Note that, due to a long-standing bug, any values that need double-quoting - typically, because they have embedded whitespace - must explicitly specify embedded, escaped double quotes as well (`"); e.g.,

"`"C:\Files A\Installer.msi`""

This would result in msiexec ... "C:\Files A\Installer.msi" getting passed through.

The problem still exists as of PowerShell [Core] 7.0, and may never be fixed in order to preserve backward compatibility. However, a new parameter may be provided to provide the correct behavior - see GitHub issue #5576.


Caveat re splatting with external programs:

When splatting with hashtables (rather than arrays), PowerShell translates the hashtable entries into
-<key>:<value> arguments
- note the : - which works well with PowerShell commands, but may not conform to the argument syntax expected by external utilities such as msiexec.
GitHub issue #9343 suggests that the format be changed to separating with a space (using separate arguments; -<key> <value>).

A simple example:

# Define hashtable with parameter name-value pairs.
$htParams = @{
   foo = 'bar none'  # parameter -foo with value 'bar none'
}

# Pass the hashtable via splatting (note the use of @ instead of $).
baz.exe @htParams

baz.exe would then see the following argument:

-foo:"bar none"
like image 115
mklement0 Avatar answered Apr 21 '26 12:04

mklement0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!