在PowerShell中从另一个函数调用一个函数

Mal*_*3nt 5 powershell workflow function powershell-workflow powershell-5.0

第一次使用PowerShell 5时,我无法调用一个将消息从另一个函数写入文件的函数。以下是我正在做的简化版本。

workflow test {
    function logMessage {
        param([string] $Msg)

        Write-Output $Msg
    }

    function RemoveMachineFromCollection{
        param([string]$Collection, [string]$Machine)

        # If there's an error
        LogMessage "Error Removing Machine"

        # If all is good
        LogMessage "successfully remove machine"
    }


    $Collections = DatabaseQuery1

    foreach -parallel($coll in $Collections) {
        logMessage "operating on $coll collection"

        $Machines = DatabaseQuery2

        foreach($Mach in $Machines) {
            logMessage "Removing $Mach from $coll"

            RemoveMachineFromCollection -Collection $coll -Machine $Mach
        }
    }
}

test
Run Code Online (Sandbox Code Playgroud)

这是它生成的错误:

术语'logMessage'不被识别为cmdlet,函数,脚本文件或可操作程序的名称。检查名称的拼写,或者是否包含路径,请验证路径是否正确,然后重试。
    + CategoryInfo:ObjectNotFound:(logMessage:String)[],CommandNotFoundException
    + FullyQualifiedErrorId:CommandNotFoundException
    + PSComputerName:[本地主机]

我尝试过在文件中四处移动logMessage函数,甚至尝试使用全局范围。

用任何其他语言,我都可以从任何其他函数中调用logMessage。这就是功能的目的。

重用代码块的“工作流方式”是什么?

我是否需要创建一些加载到工作流中的日志记录模块?

jkd*_*dba 3

您可以将函数和函数调用移动到InlineScript工作流程内的 (PowerShell ScriptBlock),如下所示。

workflow test {
    InlineScript
    {
        function func1{
            Write-Output "Func 1"
            logMessage
        }

        function logMessage{
            Write-Output "logMessage"
        }
        func1
    }
}
Run Code Online (Sandbox Code Playgroud)

会输出:

Func 1
logMessage
Run Code Online (Sandbox Code Playgroud)

正如 @JeffZeitlin 在他的回答中提到的,工作流程不是 PowerShell,而且限制性更大。InlineScript 块允许解释普通的 PowerShell 代码,但范围将绑定到 InlineScript 块。例如,如果您在脚本块中定义函数,然后尝试func1在 InlineScript 块之外(但仍在工作流程内)调用该函数,则会失败,因为它超出了范围。

如果您在工作流外部或工作流内部但不在 InlineScript 块中定义这两个函数,也会发生同样的情况。

现在通过一个示例来说明如何将其应用于运行foreach -parallel循环。

workflow test {
    ## workflow parameter
    param($MyList)

    ## parallel foreach loop on workflow parameter
    foreach -parallel ($Item in $MyList)
    {
        ## inlinescript
        inlinescript
        {
            ## function func1 declaration
            function func1{
                param($MyItem)
                Write-Output ('Func 1, MyItem {0}' -f $MyItem)
                logMessage $MyItem
            }

            ## function logMessage declaration
            function logMessage{
                param($MyItem)
                Write-Output ('logMessage, MyItem: {0}' -f $MyItem)
            }
            ## func1 call with $Using:Item statement
            ## $Using: prefix allows us to call items that are in the workflow scope but not in the inlinescript scope.
            func1 $Using:Item
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对此工作流程的调用示例如下所示

 PS> $MyList = 1,2,3
 PS> test $MyList
     Func 1, MyItem 3
     Func 1, MyItem 1
     Func 1, MyItem 2
     logMessage, MyItem: 3
     logMessage, MyItem: 2
     logMessage, MyItem: 1
Run Code Online (Sandbox Code Playgroud)

您会注意到(正如预期的那样)输出顺序是随机的,因为它是并行运行的。