【问题标题】:Can't assign value to a variable inside of Invoke-Command无法为 Invoke-Command 内的变量赋值
【发布时间】:2020-01-27 17:29:04
【问题描述】:

这似乎很奇怪,但我无法为 Invoke-Command 内的变量赋值。这是下面的代码,但是当打印出 $targetComputerPath 时,它只是空的。怎么了?

foreach ($item in $computersPath){

    $computername = $item.Name
    $username = $item.UserID

    Write-Host computer $computername and user $username

    if (Test-Connection -ComputerName $computername -Count 1 -ErrorAction SilentlyContinue)
    {
        if ($((Get-Service WinRM -ComputerName $computername).Status) -eq "stopped")
        {
          (Get-Service WinRM -ComputerName $computername).Start()
        } 
        Invoke-Command -ComputerName $computername -ScriptBlock {

        if ($((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ReleaseId) -eq "1903" ) 
            {
               $targetComputerPath = "\\"+$computername+"\c$\Users\"+$username+"\Desktop\"
               write-host "1903"
            } 
        else 
            {
              $targetComputerPath = "\\"+$computername+"\c$\Users\"+$username+"\Desktop\"
              write-host "something else"
            } 
        }
    }
    write-host $targetComputerPath
}

【问题讨论】:

  • @AdminOfThings:一般来说,是的,但是这里涉及到 remoting,所以你根本无法从 远程执行 脚本块修改调用者的变量.
  • 旁注:要找出设备的 Windows 版本,查看 AD 记录就足够了(Get-ADComputer $computername -Properties operatingSystemVersion | select name,operatingSystemVersion - 即使机器离线也可以使用)。如果这就是您需要知道的全部内容,您可以完全删除 WinRM/Invoke-Command 并大大简化您的脚本。

标签: powershell


【解决方案1】:

WinRM 的意义在于您获取一个脚本块,然后在另一台机器上执行它

您在主机脚本中定义的所有变量都不会在远程计算机上可用。

当您将“任务”(也称为脚本块)与 Invoke-Command 分开时,这一点会变得更加明显,如下所示:

$task = {
    $version = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
    if ($version.ReleaseId -eq "1903") {
        # note that `$username` cannot be available here, it's never been defined!
        return "\\$env:COMPUTERNAME\c$\Users\$username\Desktop"
    } else {
        return "\\$env:COMPUTERNAME\c$\Users\$username\Desktop"
    } 
}

foreach ($item in $computersPath) {
    $computername = $item.Name
    $username = $item.UserID

    Write-Host computer $computername and user $username

    if (Test-Connection -ComputerName $computername -Count 1 -ErrorAction SilentlyContinue) {
        $winrm = Get-Service WinRM -ComputerName $computername
        if ($winrm.Status -eq "stopped") { $winrm.Start() }
        $targetComputerPath = Invoke-Command -ComputerName $computername -ScriptBlock $task
        Write-Host "The machine returned: $targetComputerPath"
    }
}

如您所见,您可以从脚本块返回值,它们将作为Invoke-Command 的返回值提供。

如果你想将参数传递给你的脚本块,这个线程会讨论这个问题:How do I pass named parameters with Invoke-Command?

【讨论】:

  • 干得好;链接的问题更具体地说是关于将 named 参数传递给Invoke-Command;我建议(也)链接到stackoverflow.com/q/35492437/45375
  • 在这两个链接之间,OP应该能够弄清楚。
猜你喜欢
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多