Start-Process
only accepts (one or more) strings as arguments, not a script block ({ ... }
).
- While a script block is accepted, it is simply stringified, which results in its verbatim content being passed as the argument (sans
{
and }
), which means that $server
is retained as-is (not expanded), and the child process that runs your command doesn't have a variable by that name defined, causing Invoke-Command
to fail due not receiving a value for -ComputerName
.
Therefore, in order to incorporate variable values from the caller's scope, you must use string interpolation, using an expandable (double-quoted) string ("..."
) that encodes all arguments:[1]
$server = "server_name"
# Parameters -FilePath and -ArgumentList are positionally implied.
# For the resulting powershell.exe call, -Command is implied.
Start-Process powershell "
$host.ui.RawUI.WindowTitle = 'Get-Process'
Invoke-Command -ComputerName $server -ScriptBlock { Get-Process }
pause
"
A computer name ($server
, in your case) doesn't contain spaces, but any variable values that do would require embedded enclosing quoting inside the overall "..."
string, such as \`"$someVar\`"
(`"
escapes an "
inside a "..."
string in PowerShell, and the \
is additionally needed to escape the resulting verbatim "
for the PowerShell CLI, powershell.exe
).
For full robustness, additionally enclose the entire string value (implied -Command
argument) in embedded "..."
quoting ("`"...`""
).
You can make this a bit easier by using the here-string form of an expandable string (@"<newline>...<newline>"@
), inside of which you don't need to escape "
chars.
Example of a fully robust call:
$someVar = 'A value with spaces'
Start-Process powershell @"
-NoProfile -Command "
# Echo the value of $someVar
Write-Output \"$someVar\"
pause
"
"@
Note the use of -NoProfile
before -Command
, which suppresses loading of the profile files, which can speed up the call and makes for a more predictable execution environment.
[1] Technically, -ArgumentList
accepts an array of arguments, and while passing the pass-through arguments individually may be conceptually preferable, a long-standing bug unfortunately makes it better to encode all arguments in a single string - see this answer.