2014-01-23 39 views
2

我正在使用New-PSSession通过Invoke-Command在远程计算机上运行命令。举一个例子,假设我运行命令FROM的机器被称为FROM-MACHINE,并且运行命令TO的机器被称为TO-MACHINE。Powershell PSSession变量上下文

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

我希望它可以输出:

Machine name is TO-MACHINE 

但是,它实际上输出

Machine name is FROM-MACHINE 

这也发生在文件路径的情况下 - 如果我想运行一个程序在“C:\ myprogram.exe”中,powershell将尝试在“\\ FROM MACHINE \ c $ \ myprogram.exe”中找到myprogram.exe。

我的问题是:有什么办法(除了使用psexec)真正运行远程命令,变量和所有?我在这里错过简单的东西吗?

回答

1

发生这种情况是因为您正在为脚本块创建使用双引号字符串。 $ env:在创建脚本块之前,COMPUTERNAME正在扩展为本地计算机名称。如果使用单引号字符串,则$ env:COMPUTERNAME将作为文本文本传递到脚本块中,并且直到在远程计算机上执行它才会进行扩展。因此,当您从字符串创建脚本块以便在远程计算机上执行时,当您想要在脚本块中使用本地变量时,可伸缩(双引号)字符串;当您想要使用时,不可伸缩(单引号)字符串来自远程机器的变量。

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

如果你想混搭在同一个脚本块,使用可扩展的字符串,然后逃跑了所有在反引号远程变量引用$:

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

如何远程运行脚本?即使我正在运行的脚本位于不同的框中,它仍会在FROM-MACHINE的上下文中报告变量。 – finkonkanonk

+0

你测试了我发布的第二个脚本吗?它应该先返回本地机器名称,然后返回远程机器名称。 – mjolinor

+0

该脚本是否位于本地机器或远程机器上?如果它在本地机器上,我会使用Invoke-Command -FilePath。如果它位于远程机器上,则单引号字符串,或直接传递脚本块。 – mjolinor

2

你能避免通过在您的代码中直接声明您的ScriptBlock作为ScriptBlock而不是String对象来声明此情况。您只需将代码放在花括号中即可完成此操作。您可以将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; 

注意:您不必手动创建PowerShell远程会话。 Invoke-Command会照顾你,除非你特别想让它们在后台打开。