【问题标题】:How to call function outside a scriptblock如何在脚本块外调用函数
【发布时间】:2018-02-26 17:51:04
【问题描述】:

我有一个函数,我应该可以从我的 powershell 脚本中的任何位置调用它。

问题在于它不能识别脚本块中的函数。

在以下示例中,我有函数 getNumberFive,它应该返回数字 5。
当我开始一项新工作以及脚本结束时,我希望能够在脚本块中使用这个函数。

预期结果:
将数字 15 写入文件“C:\tmp\result.txt”
写入控制台:“我喜欢数字 5”

实际上:
将数字 10 写入文件“C:\tmp\result.txt”
写入控制台:“我喜欢数字 5”

我可以通过在脚本块中定义相同的函数来解决这个问题,但是我将复制该函数,这不是一个好的编程。

另一种方式是定义:

$func = {
    function getNumberFive(){
        return 5
    }
}
$scriptBlock = {

    Function printSum(){
        $number = getNumberFive
        $newNumber = 10 + $number  # => $newNumber should be 15
        $newNumber >> "C:\tmp\result.txt"
      }
}
Start-Job -ScriptBlock $scriptBlock -InitializationScript $func

但在这种情况下,我将无法拨打$five = getNumberFive

我阅读了许多方法,但我不明白如何使用它们:
CALLING A POWERSHELL FUNCTION IN A START-JOB SCRIPT BLOCK WHEN IT’S DEFINED IN THE SAME SCRIPT

How to pass a named function as a parameter (scriptblock)

https://social.technet.microsoft.com/Forums/ie/en-US/485df2df-1577-4770-9db9-a9c5627dd04a/how-to-pass-a-function-to-a-scriptblock?forum=winserverpowershell

PowerShell: Pass function as a parameter

Using Invoke-Command -ScriptBlock on a function with arguments

我的脚本:

function getNumberFive(){
    return 5
}

$scriptBlock = {

    Function printSum(){
        # $number = getNumberFive => DOESN'T WORK
        # $number = Invoke-Expression ($(get-command getNumberFive) | Select -ExpandProperty Definition) => DOESN'T WORK AS EXPECTED
        # $number = &(${function:getNumberFive}) => DOESN'T WORK AS EXPECTED
        # $number = &(Get-Item function:getNumberFive) => DOESN'T WORK AS EXPECTED
        $newNumber = 10 + $number  # => $newNumber should be 15
        $newNumber >> "C:\tmp\result.txt"
    }

    printSum
}

Start-Job -ScriptBlock $scriptBlock 

$five = getNumberFive
Write-Host "I like the number"$five

Get-Job | Wait-Job
Get-Job | Stop-Job
Get-Job | Remove-Job

【问题讨论】:

  • 试试-InitializationScript $function:getNumberFive
  • @TheIncorrigible1 它不起作用。我也试过了,在我的问题中通过在单独的脚本块中声明 getNumberFive 来查看,但是 I like the number 5 不起作用。

标签: function powershell scriptblock


【解决方案1】:

当您将脚本块传递给start-job(或invoke-expression)时,执行该脚本块的 PowerShell 实例只能访问该脚本块、脚本块加载的任何内容以及 PowerShell 实例中已存在的任何内容。

不包括脚本的其他部分。 (为了使脚本中本地定义的函数可以从其他可能是远程的 PowerShell 实例中使用,整个脚本(不仅仅是脚本块)以及任何依赖项都需要可以从其他实例访问。)

您可以将这两个地方的代码重构为脚本块加载的模块以及作业创建脚本。

使用作业时,您是在另一个进程中执行代码:与任何远程操作一样,远程执行是一个单独的环境。

【讨论】:

    【解决方案2】:

    你可以这样做:

    function getNumberFive(){
        return 5
    }
    
    $a={
    Function printSum($number){
            $newNumber = 10 + $number  # => $newNumber should be 15
            $newNumber >> "D:\result.txt"
        }
    }
    
    $scriptBlock = {
    param($number)
        printSum -number $number
    }
    $five = getNumberFive
    Write-Host "I like the number"$five
    
    Start-Job -InitializationScript $a -ScriptBlock $scriptBlock -ArgumentList $five
    

    Start-job中有一个开关名称​​-InitializationScript,你可以在其中保持你的初始化代码像一个函数。将它包装在一个脚本块中,然后从主脚本块中简单地调用它。

    希望对你有帮助。

    【讨论】:

    • 我想要这样的东西,但是$five = getNumberFive 行对我不起作用。
    • @E235:根据您的评论。我已经编辑了答案。您还必须编译该函数。
    • 我跑了,还是不行。它会打印到控制台 I like the number 5,但不会将总和 15 写入文件。您还忘记在 $initialization_block 中取消注释 $number = getNumberFive。我取消注释后检查了它。
    • 这段代码是我创建的一个非常简单的代码,目的是让事情变得足够简单,让人们理解我。真正的代码更复杂。在实际代码中,我确实需要使用start-job。我在问题中提到预期结果是将 15 写入文件并将“我喜欢数字 5”写入控制台。您的建议不会发生这种情况。
    • 这可行,但我需要找到一种方法从代码中的任何位置调用该函数。您正在使用 getNumberFive 结果,因为您知道它是恒定的。在其他情况下,它可以是一个检查脚本块内特定内容的函数。我现在没有很好的例子,因为我想让事情变得简单。我会找到并告诉你它不起作用的案例。
    猜你喜欢
    • 1970-01-01
    • 2019-01-19
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    相关资源
    最近更新 更多