【问题标题】:Powershell: passing parameters to functions stored in variablesPowershell:将参数传递给存储在变量中的函数
【发布时间】:2012-08-02 00:54:07
【问题描述】:

我试图获得一个在作业中使用函数的简单工作示例。我已经设法将我的函数传递到用于我的工作的脚本块中,但我似乎无法获取函数的参数。

# concurrency
$Logx = 
{
    param(
    [parameter(ValueFromPipeline=$true)]
    $msg
    )    
    Write-Host ("OUT:"+$msg)
}

# Execution starts here
cls
$colors = @("red","blue","green")
$colors | %{
    $scriptBlock = 
    {   
        Invoke-Expression -Command $args[1]
        Start-Sleep 3        
    } 

    Write-Host "Processing: " $_
    Start-Job -scriptblock $scriptBlock -args $_, $Logx
}

Get-Job

while(Get-Job -State "Running")
{
    write-host "Running..."
    Start-Sleep 2
}

# Output
Get-Job | Receive-Job

# Cleanup jobs
Remove-Job * 

这是输出:

Processing:  red
Id              Name            State      HasMoreData     Location             Command  
--              ----            -----      -----------     --------             -------  
175             Job175          Running    True            localhost               ...   
Processing:  blue
177             Job177          Running    True            localhost               ...   
Processing:  green
179             Job179          Running    True            localhost               ...   
179             Job179          Running    True            localhost               ...   
177             Job177          Running    True            localhost               ...   
175             Job175          Running    True            localhost               ...   
Running...
Running...
OUT:
OUT:
OUT:

正如输出中的 OUT: x3 所证明的那样,我的函数被调用了,但我没有找到任何允许我获取函数参数的语法。想法?

编辑:

请注意下面 Shawn 的观察和我的回复,我尝试使用函数作为变量,因为使用传统函数似乎不起作用。如果有办法让它工作,我会很高兴不必将我的函数作为变量传递。

【问题讨论】:

    标签: powershell powershell-jobs


    【解决方案1】:

    答案是使用Start-Job的initializationscript参数。如果您在一个块中定义所有函数并传递该块,它们将变为可用。

    在这篇文章中找到了解决方案:

    How do I Start a job of a function i just defined?

    这是我之前的示例,现在可以使用:

    # concurrency
    $func = {
        function Logx 
        {
            param(
            [parameter(ValueFromPipeline=$true)]
            $msg
            )    
            Write-Host ("OUT:"+$msg)
        }
    }
    
    # Execution starts here
    cls
    $colors = @("red","blue","green")
    $colors | %{
        $scriptBlock = 
        {   
            Logx $args[0]
            Start-Sleep 9        
        } 
    
        Write-Host "Processing: " $_
        Start-Job -InitializationScript $func -scriptblock $scriptBlock -args $_
    }
    
    Get-Job
    
    while(Get-Job -State "Running")
    {
        write-host "Running..."
        Start-Sleep 2
    }
    
    # Output
    Get-Job | Receive-Job
    
    # Cleanup jobs
    Remove-Job * 
    

    【讨论】:

      【解决方案2】:

      如果您不使用关键字 function 作为函数名称的前缀,PowerShell 不知道如何处理它。当您编写脚本时,它基本上是一个包含一些特殊文本的变量。正如您的输出所示,它仅执行它在该变量内容中识别的命令:Write-Host "OUT:"。

      使用正确的语法会告诉 PowerShell 它是一个函数,并且你有需要执行的变量传递给它:

      
      function Logx
      {
          param(
          [parameter(ValueFromPipeline=$true)]
          $msg
          )    
          Write-Host ("OUT:"+$msg)
      }
      

      然后,当您在脚本中调用它时,您只需使用 Logx

      【讨论】:

      • 这似乎不起作用,这就是为什么我在将函数设为变量时遇到了麻烦。当我将 Logx 设为传统函数并尝试使用 Logx $args[0] 代替调用表达式来调用它时,我得到:“Logx”一词未被识别为 cmdlet、函数、脚本文件或可操作的程序。检查名称的拼写,如果包含路径,请验证路径是否正确并重试。
      • 据我了解 Start-Job 启动另一个 powershell 实例,该实例没有引用父实例中定义的函数。这就是我要解决的问题。
      【解决方案3】:

      到此为止。必须用完,稍后再试。 PS:在 args[1] 传递了什么,我得到了很多红色,

       CategoryInfo          : InvalidData: (:) [Invoke-Expression], ParameterBindingValidationException
          + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand
      

      这是我到目前为止所做的。

      # concurrency
      $Logx =
      {
          param(
          [parameter(ValueFromPipeline=$true)]
          $msg
          )    
          Write-Host ("OUT:"+$msg)
      }
      
      # Execution starts here
      cls
      $colors = @("red","blue","green")
      $colors | %{
          & $scriptBlock = 
          {   Invoke-Expression -Command $args[1]
              Start-Sleep 3  
          } 
      
          Write-Host "Processing: " $_
          Start-Job -scriptblock $scriptBlock -ArgumentList @($_, $Logx)
      }
      
      # Get-Job
      
      while(Get-Job -State "Running")
      {
          write-host "Running..."
          Start-Sleep 2
      }
      
      # Output
      Get-Job | Receive-Job
      
      # Cleanup jobs
      Remove-Job * 
      

      【讨论】:

      • Args[0] 和 args[1] 是传入脚本块的 args 的位置。所以 args[1] 是 logx
      猜你喜欢
      • 2017-09-22
      • 2015-01-05
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多