12

短い質問: ForEach-Object の -RemainingScripts パラメータに関する詳細情報を知っている人はいますか?

長い質問:

先週から PowerShell の学習を始めたばかりで、詳細を学ぶために各コマンドレットを調べています。公開ドキュメントに基づいて、ForEach-Object には次のように Begin-Process-End ブロックを含めることができることがわかっています。

Get-ChildItem | foreach -Begin { "block1";
    $fileCount = $directoryCount = 0} -Process { "block2";
    if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}} -End {
    "block3"; "$directoryCount directories and $fileCount files"}

結果は期待どおりです: "block1" と "block3" に対して 1 回、"block2" は渡されたアイテムごとに繰り返され、dir カウント/ファイル カウントはすべて正しいです。ここまでは順調ですね。

さて、興味深いのは、次のコマンドも機能し、まったく同じ結果が得られることです。

Get-ChildItem | foreach { "block1"
    $fileCount = $directoryCount = 0}{ "block2";
    if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}{
    "block3"; "$directoryCount directories and $fileCount files"}

foreach に渡される ScriptBlock は 3 つだけです。マニュアルに基づいて、最初のものは -Process (Position 1) に移動します。しかし、残りの2つはどうですか?マニュアルによると、「ポジション2」のパラメータはありません。そこで、Trace-Command に目を向けると、後の 2 つのスクリプト ブロックが実際には「2 つの要素を持つ IList」として RemainingScripts にあることがわかりました。

BIND arg [$fileCount = $directoryCount = 0] to parameter [Process]
BIND arg [System.Management.Automation.ScriptBlock[]] to param [Process] SUCCESSFUL
BIND arg [System.Collections.ArrayList] to parameter [RemainingScripts]
BIND arg [System.Management.Automation.ScriptBlock[]] to param [RemainingScripts] SUCCESSFUL

したがって、コマンドを次のように変更すると:

# No difference with/without the comma "," between the last 2 blocks
Get-ChildItem | foreach -Process { "block1"
    $fileCount = $directoryCount = 0} -RemainingScripts { "block2";
    if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}},{
    "block3"; "$directoryCount directories and $fileCount files"}

それでも、まったく同じ結果です。

お気づきのように、3 つのコマンドはすべて同じ結果になります。これは興味深い質問を提起します: 後の 2 つのコマンドの両方が (暗黙的に) -Process を指定しましたが、ForEach-Object は驚くべきことに -Process の引数を "-Begin" として使用することになります! (スクリプト ブロックは最初に 1 回実行されます)。

この実験は次のことを示唆しています。

  1. -RemainingScripts パラメーターは、バインドされていない ScriptBlocks をすべて受け取ります
  2. 3つのブロックが渡されると、最初の1つは-Processに入りますが、後で実際には「Begin」として使用され、残りの2つは「Process」と「End」になります。

それでも、上記はすべて私の勝手な推測です。私の推測を裏付けるドキュメントが見つかりませんでした

それでは、最後に短い質問に戻ります :) ForEach-Object の -RemainingScripts パラメータに関する詳細な情報を知っている人はいますか?

ありがとう。

4

5 に答える 5

1

こちらがその詳細です。ValueFromRemainingArgumentstrue に設定されているので、推測は正しいです。

help ForEach-Object

-RemainingScripts <ScriptBlock[]>
    Takes all script blocks that are not taken by the Process parameter.

    This parameter is introduced in Windows PowerShell 3.0.

gcm ForEach-Object | select -exp parametersets 

Parameter Name: RemainingScripts
  ParameterType = System.Management.Automation.ScriptBlock[]
  Position = -2147483648
  IsMandatory = False
  IsDynamic = False
  HelpMessage =
  ValueFromPipeline = False
  ValueFromPipelineByPropertyName = False
  ValueFromRemainingArguments = True
  Aliases = {}
  Attributes =
    System.Management.Automation.ParameterAttribute
    System.Management.Automation.AllowEmptyCollectionAttribute
    System.Management.Automation.AllowNullAttribute
于 2013-05-20T08:12:39.760 に答える