web-dev-qa-db-ja.com

PowerShellでスクリプトブロックに引数を渡します

私はあなたがこれを行うことはできないと思います:

  $servicePath = $args[0]

  if(Test-Path -path $servicePath) <-- does not throw in here

  $block = {

        write-Host $servicePath -foreground "Magenta"

        if((Test-Path -path $servicePath)) { <-- throws here.

              dowork 
        }
  }

それでは、変数をscriptblock $ blockに渡すにはどうすればよいですか?

39
dexter

キースの答えInvoke-Commandでも機能しますが、名前付きパラメーターを使用できないという制限があります。引数は-ArgumentListパラメーターを使用して設定し、コンマで区切る必要があります。

$sb = {param($p1,$p2) $OFS=','; "p1 is $p1, p2 is $p2, rest of args: $args"}
Invoke-Command $sb -ArgumentList 1,2,3,4

here および here も参照してください。

43
Lars Truijens

スクリプトブロックは、単なる匿名関数です。スクリプトブロック内で$argsを使用したり、paramブロックを宣言したりできます。たとえば、

$sb = {
  param($p1, $p2)
  $OFS = ','
  "p1 is $p1, p2 is $p2, rest of args: $args"
}
& $sb 1 2 3 4
& $sb -p2 2 -p1 1 3 4
30
Keith Hill

ところで、スクリプトブロックを使用して別のスレッド(マルチスレッド)で実行する場合:

$ScriptBlock = {
    param($AAA,$BBB) 
    return "AAA is $($AAA) and BBB is $($BBB)"
}

$AAA = "AAA"
$BBB = "BBB1234"    
$null = Start-Job $ScriptBlock -ArgumentList $AAA,$BBB

その後、生成されます:

$null = Start-Job $ScriptBlock -ArgumentList $AAA,$BBB    
Get-Job | Receive-Job
AAA is AAA and BBB is BBB1234
6

私はこの記事が少し時代遅れであることを知っていますが、可能な代替手段としてこれを捨てたかったのです。前の回答のわずかなバリエーション。

$foo = {
    param($arg)

    Write-Host "Hello $arg from Foo ScriptBlock" -ForegroundColor Yellow
}

$foo2 = {
    param($arg)

    Write-Host "Hello $arg from Foo2 ScriptBlock" -ForegroundColor Red
}


function Run-Foo([ScriptBlock] $cb, $fooArg){

    #fake getting the args to pass into callback... or it could be passed in...
    if(-not $fooArg) {
        $fooArg = "World" 
    }
    #invoke the callback function
    $cb.Invoke($fooArg);

    #rest of function code....
}

Clear-Host

Run-Foo -cb $foo 
Run-Foo -cb $foo 

Run-Foo -cb $foo2
Run-Foo -cb $foo2 -fooArg "Tim"
1
SpaceGhost440

デフォルトでは、PowerShellはScriptBlockの変数をキャプチャしません。ただし、GetNewClosure()を呼び出すことで明示的にキャプチャできますが、次のようになります。

$servicePath = $args[0]

if(Test-Path -path $servicePath) <-- does not throw in here

$block = {

    write-Host $servicePath -foreground "Magenta"

    if((Test-Path -path $servicePath)) { <-- no longer throws here.

          dowork 
    }
}.GetNewClosure() <-- this makes it work
1