简体   繁体   English

Powershell PSSession变量上下文

[英]Powershell PSSession variable context

I am using New-PSSession to run a command on a remote machine, via Invoke-Command. 我正在使用New-PSSession通过Invoke-Command在远程计算机上运行命令。 As an example, let's say the machine I am running the command FROM is called FROM-MACHINE, and the machine I am running the command TO is called TO-MACHINE. 例如,假设我运行命令FROM的计算机称为FROM-MACHINE,而我运行命令TO的计算机称为TO-MACHINE。

$session = New-PSSession -ComputerName TO-MACHINE
$script = ScriptBlock::Create("Write-Host Machine name is $env:COMPUTERNAME")
Invoke-Command -session $session -scriptBlock $script

I would expect this to output: 我希望这能输出:

Machine name is TO-MACHINE

However, it actually outputs 但是,它实际上输出

Machine name is FROM-MACHINE

This also happens in the case of file paths - if I want to run a program at "C:\\myprogram.exe" powershell will attempt to find myprogram.exe at "\\\\FROM-MACHINE\\c$\\myprogram.exe". 在文件路径的情况下也会发生这种情况-如果我想在“ C:\\ myprogram.exe”中运行程序,PowerShell将尝试在“ \\\\ FROM-MACHINE \\ c $ \\ myprogram.exe”中找到myprogram.exe。

My question is this: is there any way (other than using psexec) to truly run a remote command, variables and all? 我的问题是:除了真正使用psexec之外,还有什么方法可以真正地运行远程命令,变量和全部? Am I missing something simple here? 我在这里缺少简单的东西吗?

You can avoid this situation by declaring your ScriptBlock directly in your code as a ScriptBlock instead of a String object. 通过在代码中直接将ScriptBlock声明为ScriptBlock而不是String对象,可以避免这种情况。 You do this by simply surrounding the code in curly braces. 您只需将代码括在花括号中即可。 You can store the ScriptBlock object in a variable, and then pass it into Invoke-Command just as you were before, with the -ScriptBlock parameter. 您可以将ScriptBlock对象存储在变量中,然后使用-ScriptBlock参数像以前一样将其传递到Invoke-Command

$ScriptBlock = {
    $Program = 'c:\MyProgram.exe';
    Start-Process -Wait -FilePath $Program -ArgumentList 'args go here';

    Write-Host -Object "Write-Host Machine name is $env:COMPUTERNAME";
    }

Invoke-Command -ComputerName to-machine -ScriptBlock $ScriptBlock;

Note : You do not have to manually create PowerShell Remoting sessions. 注意 :您不必手动创建PowerShell Remoting会话。 Invoke-Command will take care of that for you, unless you specifically want to leave them open in the background. 除非您特别想让它们在后台保持打开状态,否则Invoke-Command会为您解决这些问题。

This is happening because you are using a double quoted string for your script block creation. 发生这种情况是因为您在脚本块创建中使用了双引号引起来的字符串。 $env:COMPUTERNAME is being expanded to the local computer name before the script block is created. 在创建脚本块之前,将$ env:COMPUTERNAME扩展为本地计算机名称。 If you use a single-quoted string, $env:COMPUTERNAME will get passed in the script block as literal text, and expansion won't happen until it gets executed on the remote machine. 如果使用单引号引起来的字符串,$ env:COMPUTERNAME将在脚本块中以原义文本形式传递,并且扩展不会发生,直到在远程计算机上执行它为止。 So, when you're creating script blocks from strings for execution on remote machines, us expandable (double quoted) strings when you want to use local variables in the script block, and non-expandable (single quoted) strings when you want to use variables from the remote machine. 因此,当您从字符串中创建脚本块以在远程计算机上执行时,当您要在脚本块中使用局部变量时,我们使用可扩展(双引号)字符串,而当您要使用时使用非扩展(单引号)字符串远程计算机上的变量。

$session = New-PSSession -ComputerName TO-MACHINE
$script = [ScriptBlock]::Create('$env:COMPUTERNAME')
Invoke-Command -session $session -scriptBlock $script

If you want to mix and match in the same script block, use an expandable string, and then escape the $ on all the remote variable references with a backtick: 如果要在同一脚本块中混合使用,请使用可扩展字符串,然后使用反引号对所有远程变量引用中的$进行转义:

$session = New-PSSession -ComputerName TO-MACHINE 
$script = [ScriptBlock]::Create(" Write-output $env:Computername; Write-Output `$env:COMPUTERNAME ")
Invoke-Command -session $session -scriptBlock $script

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM