How to pass $_ ($PSItem) in a ScriptBlock

后端 未结 3 635
执笔经年
执笔经年 2021-01-06 07:51

I\'m basically building my own parallel foreach pipeline function, using runspaces.

My problem is: I call my function like this:

somePipeline | MyNew         


        
相关标签:
3条回答
  • 2021-01-06 08:12

    Maybe this can help. I'd normally run auto-generated jobs in parallel this way:

    Get-Job | Remove-Job
    
    foreach ($param in @(3,4,5)) {
    
     Start-Job  -ScriptBlock {param($lag); sleep $lag; Write-Output "slept for $lag seconds" } -ArgumentList @($param)
    
    }
    
    Get-Job | Wait-Job | Receive-Job
    

    If I understand you correctly, you are trying to get rid of param() inside the scriptblock. You may try to wrap that SB with another one. Below is the workaround for my sample:

    Get-Job | Remove-Job
    
    #scriptblock with no parameter
    $job = { sleep $lag; Write-Output "slept for $lag seconds" }
    
    foreach ($param in @(3,4,5)) {
    
     Start-Job  -ScriptBlock {param($param, $job)
      $lag = $param
      $script = [string]$job
      Invoke-Command -ScriptBlock ([Scriptblock]::Create($script))
     } -ArgumentList @($param, $job)
    
    }
    
    Get-Job | Wait-Job | Receive-Job
    
    0 讨论(0)
  • 2021-01-06 08:14
    # I was looking for an easy way to do this in a scripted function,
    # and the below worked for me in PSVersion 5.1.17134.590
    
    function Test-ScriptBlock {
        param(
            [string]$Value,
            [ScriptBlock]$FilterScript={$_}
        )
        $_ = $Value
        & $FilterScript
    }
    Test-ScriptBlock -Value 'unimportant/long/path/to/foo.bar' -FilterScript { [Regex]::Replace($_,'unimportant/','') }
    
    0 讨论(0)
  • 2021-01-06 08:15

    The key is to define $_ as a variable that your script block can see, via a call to Set-Variable.

    Here's a simple example:

    function MyNewForeachFunction {
      [CmdletBinding()]
      param(
        [Parameter(Mandatory)]
        [scriptblock] $ScriptBlock
        ,
        [Parameter(ValueFromPipeline)]
        $InputObject
      )
    
      process {
        $PSInstance = [powershell]::Create()
    
        # Add a call to define $_ based on the current pipeline input object
        $null = $PSInstance.
          AddCommand('Set-Variable').
            AddParameter('Name', '_').
            AddParameter('Value', $InputObject).
          AddScript($ScriptBlock)
    
        $PSInstance.Invoke()
      }
    
    }
    
    # Invoke with sample values.
    1, (Get-Date) | MyNewForeachFunction { "[$_]" }
    

    The above yields something like:

    [1]
    [10/26/2018 00:17:37]
    
    0 讨论(0)
提交回复
热议问题