elpe
elpe

Reputation: 33

How to pass a variable to new console window in Powershell

I want to pass a variable to a new console, but I don't know how.

$server = "server_name"
Start-Process Powershell {
      $host.ui.RawUI.WindowTitle = “Get-Process”
      Invoke-Command -ComputerName $server -ScriptBlock {
             Get-Process
      }
cmd /c pause
}

Error message:

Invoke-Command : Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again

Upvotes: 2

Views: 1658

Answers (2)

mklement0
mklement0

Reputation: 437318

  • 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.

Upvotes: 4

Tal Folkman
Tal Folkman

Reputation: 2571

if you want to use param-

info

param([type]$p1 = , [type]$p2 = , ...)

or:

info

param(
[string]$server 
)

Write-Host $a

./Test.ps1 "your server name"

Upvotes: 0

Related Questions