Search code examples
powershellquotingstart-process

How to pass parameters as part of -file in PowerShell


If I run this line in a PowerShell window, it executes perfectly

.\buildTestAndPublish.ps1 -buildPath 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0' -testPath 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow'

Now I need to automate this and I'm failing to do so

$pth = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0'
$testPth = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow' 
start-process powershell -Verb runAs -ArgumentList "-file $PSScriptRoot\AutomationScripts\buildTestAndPublish.ps1 -buildPath $pth -testPath $testPth"

A positional parameter could not be found that accepts argument Files

This looks like it's complaining about the white space, but after a search, I've wrapped them in single quote marks AND pass them as variables (the advice I found online)

What do I need to do?


Solution

  • Use embedded double-quoting around the arguments that may contain spaces; inside "...", escape embedded " as `", because `, the backtick character[1] , is PowerShell's escape character:

    "-file $PSScriptRoot\buildTestAndPublish.ps1 -buildPath `"$pth`" -testPath `"$testPth`""
    

    Note: *.ps1 path shortened for readability.

    Note: Embedded single-quoting ('...') does not work in this case, because using the PowerShell CLI with -File doesn't recognize single quotes as string delimiters; by contrast, they are recognized as such with -Command.[2]


    Note that you could alternatively pass the arguments invidually, as an array to -ArgumentList.
    However, due to a known bug you must still apply embedded double-quoting:

    Start-Process powershell -Verb runAs -ArgumentList '-file',
      $PSScriptRoot\AutomationScripts\buildTestAndPublish.ps1,
      '-buildPath',
      "`"$pth`"",
      '-testPath',
      "`"$testPth`""
    

    [1] Formally known as GRAVE ACCENT, Unicode code point U+0060.

    [2] As such, you could have used -Command instead of -File, which would then enable the following solution:
    "-Command $PSScriptRoot\buildTestAndPublish.ps1 -buildPath '$pth' -testPath '$testPth'", but (a) ' is a legal character in filenames (whereas " is not) and the presence of ' in a filename would break the command; and (b) -Command treats the arguments as PowerShell code, which can lead to additional unwanted interpretation (by contrast, -File treats its arguments as literals).