2014-01-23 45 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會照顧你,除非你特別想讓它們在後臺打開。