3

My PowerShell script should start an external executable with specified parameters. I have two strings: The file name, and the arguments. This is what process starting APIs usually want from me. PowerShell however fails at it.

I need to keep the executable and arguments in a separate strings because these are configured elsewhere in my script. This question is just about using these strings to start the process. Also, my script needs to put a common base path in front of the executable.

This is the code:

$execFile = "SomeSetup.exe"
$params = "/norestart /verysilent"
& "$basePath\$execFile" $params | Out-Host
# Pipe to the console to wait for it to finish

This is the actual result (does not work with this program):

  • Process file name: "C:\My\Base path\SomeSetup.exe"
  • Process command line: "/norestart /verysilent"

This is what I'd expect to have (this would work):

  • Process file name: "C:\My\Base path\SomeSetup.exe"
  • Process command line: /norestart /verysilent

The problem is that the setup recognises the extra quotes and interprets the two arguments as one - and doesn't understand it.

I've seen Start-Process but it seems to require each parameter in a string[] which I don't have. Splitting these arguments seems like a complicated shell task, not something I'd do (reliably).

What could I do now? Should I use something like

& cmd /c "$execFile $params"

But what if $execFile contains spaces which can well happen and usually causes much more headache before you find it.

ygoe
  • 18,655
  • 23
  • 113
  • 210

5 Answers5

3

You can put your parameters in an array:

$params = "/norestart", "/verysilent"
& $basepath\$execFile $params
Jason Shirk
  • 7,734
  • 2
  • 24
  • 29
2

When you run a legacy command from Powershell it has to convert the powershell variables into a single string that is the legacy command line.

  • The program name is always enclosed in quotes.
  • Any parameters that contain a space character are enclosed in double quotes (this is of course the source of your problem)
  • Each element of an array forms a separate argument.

So given:

$params = "/norestart /verysilent"
& "$basePath\$execFile" $params

Powershell will run the command:

"\somepath\SomeSetup.exe" "/norestart /verysilent"

The solution is to store separate arguments in an array:

$params = "/norestart","/verysilent"
& "$basePath\$execFile" $params

will run:

"\somepath\SomeSetup.exe" /norestart /verysilent

Or if you already have a single string:

$params = "/norestart /verysilent"
& "$basePath\$execFile" ($params -split ' ')

will work as well.

Duncan
  • 92,073
  • 11
  • 122
  • 156
0

Try it this way:

& $execFile /norestart /verysilent

Bill

Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62
  • 1
    I need to pass the arguments from another configuration section, so this is not configurable enough. – ygoe Feb 25 '14 at 17:08
0
$execFile = "SomeSetup.exe"
$params = "/norestart /verysilent"
Invoke-Expression ($basePath + "\" + $execFile + " " +$params)
Raf
  • 9,681
  • 1
  • 29
  • 41
  • According to Microsoft, `Invoke-Expression` is an alias for `&`. And you're missing the quotes around the executable file name. – ygoe Feb 25 '14 at 17:09
  • It's not missing anything boss, we are creating a string on the fly ;) Try it with `$execFile = "ipconfig"; $params = "/all"; Invoke-Expression ($execFile + " " +$params)` – Raf Feb 25 '14 at 17:25
  • I amended the answer to include your `$basepath` – Raf Feb 25 '14 at 17:31
  • 1
    @LonelyPixel - Invoke-Expression is not an alias for &. Invoke-Expression is roughly: write this string out to ps1 file, then run the ps1 file. & is the invocation operator - it just means - the next value (typically a string or variable) names a command to run. – Jason Shirk Feb 25 '14 at 17:33
  • 1
    Oh cool, German translation is different from English page: http://technet.microsoft.com/de-de/library/ee176880.aspx I'll try this tomorrow. – ygoe Feb 25 '14 at 19:46
  • This works: `Invoke-Expression ($basePath + "\" + $file + " " + $params + " | Out-Host")` – ygoe Feb 26 '14 at 09:22
  • 1
    Not the prettiest code on earth, but accepted because it's the first and only answer that actually works. – ygoe Feb 26 '14 at 09:25
-1

Just use single quotes:

$execFile = "SomeSetup.exe"
$params = "/norestart /verysilent"
& "'$basePath\$execFile' $params" | Out-Host
# Pipe to the console to wait for it to finish

Also I would use join-path instead of concatenating the two strings:

$path = Join-Path $basePath $execFile
& "$path $params" | out-host
Cole9350
  • 5,444
  • 2
  • 34
  • 50
  • 1
    Does not work. It tries to find the complete string incl. space and parameters as command and fails. – ygoe Feb 26 '14 at 09:24