I have the below code line, in a script that iterates through things to install from a repository. Some things have arguments, some don't. Have come across one that doesn't, and trying to avoid having the same command more or less duplicated (along with all the error checking, etc) in a for...else command. Is there anyway to have start-process work with a $null/empty variable specified after -argumentlist
that I am not thinking about?
for($i=0; $i -lt $Installs.count; $i++)
{
$Arguments = $($Installs[$i].path)
start-process -filepath $Path -argumentlist $Arguments -wait
}
I have the below code line, in a script that iterates through things to install from a repository. Some things have arguments, some don't. Have come across one that doesn't, and trying to avoid having the same command more or less duplicated (along with all the error checking, etc) in a for...else command. Is there anyway to have start-process work with a $null/empty variable specified after -argumentlist
that I am not thinking about?
for($i=0; $i -lt $Installs.count; $i++)
{
$Arguments = $($Installs[$i].path)
start-process -filepath $Path -argumentlist $Arguments -wait
}
Share
Improve this question
edited Jan 29 at 17:40
user66001
asked Jan 29 at 16:53
user66001user66001
9151 gold badge15 silver badges37 bronze badges
0
2 Answers
Reset to default 3Your symptom suggests that you're using Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1), where
Start-Process
's-ArgumentList
parameter inexplicably doesn't accept$null
,@()
(an empty array / enumerable) or''
(the empty string).Fortunately, this unhelpful constraint has been removed in PowerShell (Core) 7, which now interprets any of these inputs as the signal to pass no arguments, i.e. to behave the same as if
-ArgumentList
hadn't been specified at all. In other words: your code would work as-is there.
However, the splatting technique described in Santiago's answer alone is not enough for a robust solution:
- A long-standing
Start-Process
bug that won't be fixed (see GitHub issue #5565) unfortunately requires use of embedded double-quoting around arguments that contain spaces, e.g.-ArgumentList '-foo', '"bar baz"'
Therefore, use the following:
for ($i = 0; $i -lt $Installs.count; $i++)
{
# Create a hashtable for splatting that originally just contains
# a value for the -FilePath and -Wait parameters.
$splat = @{
FilePath = $Path
Wait = $true
}
# Only add an 'ArgumentList' entry if an install path was given.
if ($installPath = $Installs[$i].Path) {
# Enclose the install path in "..." if it contains spaces.
$splat.ArgumentList =
($installPath, "`"$installPath`"")[$installPath -match ' ']
}
# Note the use of @ instead of $ in order to achieve splatting.
Start-Process @splat
}
Note:
The
($installPath = $Installs[$i].Path)
conditional:Assigns the value of
$Installs[$i].Path
to helper variable$installPath
...... and - due to enclosure of the assignment in
(...)
) - outputs the assigned value, which is then tested using implicit to-Boolean coercion:The value is assumed to be a string, and PowerShell coerces any nonempty string to
$true
, so thatif ($Installs[$i].Path)
is in effect shorthand forif ('' -ne $Installs[$i].Path)
($installPath, "`"$installPath`"")[$installPath -match ' ']
is an approximation of a ternary conditional, that is, in effect, short for:
if ($installPath -match ' ') { "`"$installPath`"" } else { $installPath }
; see this answer for details.- Note that, in PowerShell 7, true ternary conditionals are now available, so you could write,
$installPath -match ' ' ? "`"$installPath`"" : $installPath
- Note that, in PowerShell 7, true ternary conditionals are now available, so you could write,
Typically you'll also get away with unconditionally double-quoting arguments, which would simplify matters to:
$splat.ArgumentList = "`"$installPath`""
It's unclear why you're using a for
loop instead of a foreach
loop, but using splatting should work for your use case, it does require an if
condition tho:
for ($i = 0; $i -lt $Installs.count; $i++) {
$Arguments = @{}
if ($Installs[$i].path) { $Arguments['ArgumentList'] = $Installs[$i].path }
Start-Process -FilePath $Path @Arguments -Wait
}
This would be another option too, splatting all arguments and adding the optional one to the splatting hash:
for ($i = 0; $i -lt $Installs.count; $i++) {
$startProcessSplat = @{
FilePath = $Path
Wait = $true
}
if ($Installs[$i].path) {
$startProcessSplat['ArgumentList'] = $Installs[$i].path
}
Start-Process @startProcessSplat
}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745288714a4620725.html
评论列表(0条)