【问题标题】:PowerShell ScriptBlock and multiple functionsPowerShell ScriptBlock 和多种功能
【发布时间】:2021-06-07 19:33:40
【问题描述】:

我写了以下代码:

cls
function GetFoo() { 
    function GetBar() {
        $bar = "bar"
        $bar
    }

    $foo = "foo"
    $bar = GetBar
    $foo
    $bar
}


$cred = Get-Credential "firmwide\srabhi_adm"
$result = Invoke-Command -Credential $cred -ComputerName localhost 
-ScriptBlock ${function:GetFoo}
Write-Host $result[0]
Write-Host $result[1]

它有效,但我不想在 GetFoo 内定义 GetBar

我可以这样做吗?

cls
function GetBar() {
    $bar = "bar"
    $bar
}

function GetFoo() {     
    $foo = "foo"
    $bar = GetBar
    $foo
    $bar
}


$cred = Get-Credential "firmwide\srabhi_adm"
$result = Invoke-Command -Credential $cred -ComputerName localhost 
-ScriptBlock ${function:GetFoo; function:GetBar; call GetFoo}
Write-Host $result[0]
Write-Host $result[1]

基本上,我有选择地将我想要的函数放入 ScriptBlock 中,然后调用其中一个。这样我就不必在函数内部定义函数,我可以通过注入我想成为该 ScriptBlock 一部分的函数来构造 ScriptBlock。

【问题讨论】:

    标签: powershell powershell-remoting scriptblock


    【解决方案1】:

    问题是Invoke-Command 只能看到ScriptBlock 里面的东西,它看不到外面定义的函数。如果您真的想要 - 您可以在一行中运行所有内容,如下所示:

    $result = Invoke-Command  -ComputerName localhost  -ScriptBlock { function GetBar() { $bar = "bar"; $bar }; function GetFoo() { $foo = "foo"; $bar = GetBar; $foo;  $bar }; GetFoo }
    

    但我个人建议你将函数保存在脚本中,并使用-FilePath 参数调用Invoke-Command,如下所示:

    $result = Invoke-Command  -ComputerName localhost  -FilePath "\1.ps1"
    

    【讨论】:

      【解决方案2】:

      我知道这是一个旧线程,但我希望它对某人有所帮助。

      [CmdletBinding()]
      param()
      $barScriptBlock = {
          function GetBar() {
              $bar = "bar"
              $bar
          }
      }
      $fooScriptBlock = {
          function GetFoo() {     
              $foo = "foo"
              $bar = GetBar
              $foo
              $bar
          }
      }
      # Concatenate all functions into a script block; add a parameter for extra credit.
      $scriptBlockString = @"
      param(`$hello)
      $($barScriptBlock.ToString())
      $($fooScriptBlock.ToString())
      `$hello
      GetFoo
      "@
      Write-Verbose $scriptBlockString
      # Convert combined string to script block.
      $finalScriptBlock = [ScriptBlock]::Create($scriptBlockString)
      # Run synchronously, passing runtime parameter.
      $result = & $finalScriptBlock "Hola"
      # (Async results would not be reiably accessed here yet.)
      Write-Host $result[0]
      Write-Host $result[1]
      Write-Host $result[2]
      

      【讨论】:

        【解决方案3】:

        我最近得到了这个工作:

        function GetBar() {
            $bar = "bar"
            $bar
        }
        
        function GetFoo() {     
            $foo = "foo"
            $bar = GetBar
            $foo
            $bar
        }
        
        $NewScriptBlock = [scriptblock]::Create("function GetBar() { ${function:GetBar} } function GetFoo() { ${function:GetFoo} } GetFoo")
        Invoke-Command -ComputerName localhost -ScriptBlock $NewScriptBlock
        

        或者,您可以使用以下命令保留一行:

        Invoke-Command -ComputerName localhost -ScriptBlock ([scriptblock]::Create("function GetBar() { ${function:GetBar} } function GetFoo() { ${function:GetFoo} } GetFoo"))
        

        诀窍是 ScriptBlock 类的 Create 方法在函数内部添加代码,但不添加标题和最后的括号。您需要自己添加,加上最后的调用。

        【讨论】:

          【解决方案4】:

          Joe Zamora's answer 为基础,这是我认为更适合该问题的命令:

          $result = Invoke-Command -Credential $cred -ScriptBlock ([ScriptBlock]::Create("${function:GetFoo}; ${function:GetBar}; GetFoo"))
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-07-09
            • 2017-06-20
            • 1970-01-01
            • 2021-01-29
            • 2020-08-03
            • 2018-10-06
            • 1970-01-01
            相关资源
            最近更新 更多