【问题标题】:Variable is not sent to remote session [duplicate]变量未发送到远程会话[重复]
【发布时间】:2016-07-30 13:23:27
【问题描述】:

我有下面我一直在处理的代码,但我有一个问题,我无法让它将变量消息发送到计算机,如果我取出变量它可以工作,但这不是我想要的完成它。

Function Send-PopupMessage {
    #Requires -Version 2.0 
    [CmdletBinding()]  
    Param(
        [Parameter(Mandatory = $true)]
        [String]$ComputerName,
        [Parameter(Mandatory = $true)]
        [String]$Message
    )

    Invoke-Command -ComputerName $ComputerName -Scriptblock {
        $CmdMessage = "msg.exe * $Message"
        Write-Host $CmdMessage
        $CmdMessage | Invoke-Expression
    }
}

这与question linked 不同,因为我正在使用 PSWA 与另一台计算机进行会话,因此我无法从此开始另一个会话。此外,即使我将代码更改为更像“重复”问题中的代码,我仍然得到与发送到另一台计算机的 cmd 相同的结果

msg.exe * '' 代替 msg.exe * '测试消息'

【问题讨论】:

  • 简而言之:使用$using:Message 以引用$Messagelocal 定义。

标签: powershell powershell-3.0


【解决方案1】:

默认情况下,PowerShell 脚本块不是词法闭包。传递给 Invoke-Command 的脚本块在另一台计算机上运行时不会保存 $Message 参数的当前值。

当块在远程会话中运行时,它在该会话中使用$Message 的当前值。由于该变量很可能是 $null,因此您的命令中会省略该消息。

使用$using:variable语法described in this question捕获$Message的值。

Invoke-Command -ComputerName $ComputerName -Scriptblock {
    $CmdMessage = "msg.exe * $using:Message"
    Write-Host $CmdMessage
    $CmdMessage | Invoke-Expression
}

$using:variable 语法仅在调用远程计算机上的块时有效。如果您需要捕获脚本块中的变量以供本地执行,请改为在 ScriptBlock 上调用 GetNewClosure()

$Message = "Hey there."
$closure = {
    $CmdMessage = "msg.exe * $Message"
    Write-Host $CmdMessage
    $CmdMessage | Invoke-Expression
}.GetNewClosure()

$Message = $null
Invoke-Command -Scriptblock $closure

【讨论】:

  • 虽然您的解释是正确的,但我认为您的解决方案不起作用:假设您的本地计算机设置为远程处理,对比以下命令(只有最后一个有效):$foo = 'bar'; icm -computername . { $foo } vs .$foo = 'bar'; icm -computername . { $foo }.GetNewClosure()$foo = 'bar'; icm -computername . { $using:foo }
  • AFAIK,对于远程调用 Invoke-Command 是忽略任何附加到 ScriptBlock 的模块,所以 GetNewClosure() 在这里没用。
  • 编辑了答案以包含 $using:var 语法,尽管我同意这可能会使这成为一个骗局。谢谢@mklement0
  • 如果您不使用-ComputerNameInvoke-Command,则在当前范围内执行本地执行,本地变量可以直接访问 - 不需要.GetNewClosure()。比较$foo = 'bar'; icm { $foo },它实际上与$foo = 'bar'; & { $foo } 相同。我不清楚何时真正需要 .GetNewClosure()
  • GetNewClosure 在调用时保存变量的状态。在上面的示例中,$Message 变量设置为 null,但脚本块调用仍使用其旧值。我用它来保存变量状态以供以后执行。
猜你喜欢
  • 2014-04-16
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
相关资源
最近更新 更多