2012-03-06 18 views
6

私は本の中でPowerShellを学んだことについて混乱しています。第21章では、パラメータバインディングやパイプライン経由で入力を受け付ける関数について、2つのパターンを示します。このPowershell関数のパイプラインとパラメータの入力を処理する

function someworkerfunction { 
# do stuff 
} 
function Get-Work { 
    [CmdletBinding()] 
    param(
     [Parameter(Mandatory=$True, 
     ValueFromPipelineByPropertyName=$True)] 
     [Alias('host')] 
     [string[]]$computername 
    ) 
    BEGIN {} 
    PROCESS { 
     foreach($computer in $computername) { 
     someworkerfunction -comptuername $computer 
     } 
    } 
    END {} 
} 

function someworkerfunction { 
# do some work 
} 
function Get-SomeWork { 
    param ([string[]]$computername) 
    BEGIN { 
     $usedParameter = $False 
     if($PSBoundParameters.ContainsKey('computername')) { 
     $usedParameter = $True 
     } 
    } 
    PROCESS { 
     if($usedParameter) { 
     foreach($computer in $computername) { 
      someworkerfunction -computername $comptuer 
     } 
     } else { 
     someworkerfunction -comptuername $_ 
     } 
    } 

    END {} 
} 

秒を次のように

最初のIは、第二のサンプルは、標準のPowershell 2.0高度な機能を知っています。私の質問は、Powershell 2.0のcmdletbindingディレクティブのサポートで、これまでに最初のパターンを使用したいと思うでしょう。それはPowershell 1.0の単なる遺産ですか?基本的には、Powershell 2.0を使用しているときに、最初のパターンを混乱させたい時があります.2番目のパターンがとてもきれいです。

洞察力があれば幸いです。

ありがとうございます。

答えて

3

関数でパイプライン入力を処理したいが、すべてのパラメータ属性を追加したくない場合、または下位互換性を持たせたい場合は、cmdletbindingを使います。

パラメータ属性、パラメータセットなどのPowerShellスクリプトコマンドレットの追加機能を使用する場合は、2番目のコマンドを使用します。

0

最初の形式では、引数リストまたはパイプラインから文字列引数として1つ以上のコンピュータ名が必要です。

第2の形式では、引数リストの文字列引数の配列、またはコンピュータ名をプロパティとして持つパイプラインの入力オブジェクトが必要です。

1

あなたの質問に答えるには、最初のパターンはPowerShell 1.0の遺産に過ぎないと思いますが、$inputもProcessスクリプトブロックなしの古典的な関数で使用できます。あなたがPowerShell 2.0用のコードを書いている限り、あなたはそれを忘れることができます。

パイプライン機能に関しては、powerShell V1.0ではfiltersで処理できます。

ネットからサンプルを取得するときや、古いPowerhellコードをデバッグするときに、そのようになっていることがわかります。

個人的に私はまだ私のモジュールの中に古いfunctionsfiltersを使用していますが、私はcmdletbindingをエクスポート機能またはプロファイル機能用に予約しています。

Powershellは、レゴブロックのようなビットです。さまざまな方法で多くのことを行うことができます。

+0

こんにちは。情報ありがとうございます。これは私が知りたかったものです。 – lowteq

1

この^は、私はこの質問を持っていたときので、私は多くの時間を保存しているだろう、誰もがパイプで連結された入力から読み取る方法の非常に、非常に簡単な説明を希望する場合

How do you write a powershell function that reads from piped input?

を参照存在していましたこのスレッドは非常に複雑で、パイプライン入力を関数にどのように扱うかを実際には説明しません。

2

いいえ、最初の例は単なるレガシーではありません。配列パラメーターを使用し、パイプライン入力を受け取るPowerShell関数を作成するには、いくつかの作業が必要です。

私は、2番目の例がうまくいきません。少なくとも私はそれを働かせることができませんでした。

この例を見てみましょう...

function PipelineMadness() 
{ 
    [cmdletbinding()] 
    param (
     [Parameter(Mandatory = $true, ValueFromPipeline=$true)] 
     [int[]] $InputArray 
    ) 

    Write-Host ('$InputArray.Count {0}' -f $InputArray.Count) 
    Write-Host $InputArray 

    Write-Host ('$input.Count {0}' -f $input.Count) 
    Write-Host $input 

    if($input) { Write-Host "input is true" } 
    else { Write-Host "input is false" } 
} 

結果...パイプラインを使用する場合$InputArray変数が5の単一の値であることを

PS C:\Windows\system32> 1..5 | PipelineMadness 
$InputArray.Count 1 
5 
$input.Count 5 
1 2 3 4 5 
input is true 

PS C:\Windows\system32> PipelineMadness (1..5) 
$InputArray.Count 5 
1 2 3 4 5 
$input.Count 1 

input is false 

お知らせ...

今すぐBEGINとPROCESSブロックを使って

それは奇妙な

PS C:\Windows\system32> 1..5 | PipelineMadnessProcess 
BEGIN 
$InputArray.Count 0 

$input.Count 0 

input is false 
PROCESS 
$InputArray.Count 1 
1 
$input.Count 1 
1 
input is true 
PROCESS 
$InputArray.Count 1 
2 
$input.Count 1 
2 
input is true 

... 

PROCESS 
$InputArray.Count 1 
5 
$input.Count 1 
5 
input is true 

を取得する場所さて、これはBEGINブロックが全くそこに任意のデータを持っていないです。プロセスブロックはうまく動作しますが、実際に動作する例のようなforeachがある場合、1エントリX回でforeachが実行されます。または、配列を渡した場合は、フルセットで一度foreachを実行します。

私は技術的にはこの例がうまくいくと思っていますが、期待通りに機能しないかもしれません。

また、BEGINブロックにデータがない場合でも、関数は構文検証に合格しました。

関連する問題