2012-03-06 102 views
6

對於我在一個午餐月的Learn PowerShell一書中看到的內容感到困惑。在第21章中,當作者討論通過參數綁定或流水線接受輸入的函數時,他給出了兩種模式。在Powershell函數中處理管道和參數輸入

第一如下

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 {} 
} 

第二像這樣

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 {} 
} 

我知道第二樣品是標準Powershell的2.0高級功能。我的問題是與Powershell 2.0的cmdletbinding指令的支持,你會想要使用第一種模式。這僅僅是Powershell 1.0的遺產嗎?基本上是有一段時間,當我使用Powershell 2.0的時候,當第二種模式變得非常乾淨時,我會想要使用第一種模式。

任何有識之士將不勝感激。

謝謝。

回答

3

如果要處理管道輸入您的功能,但不希望添加所有的參數屬性或想向後兼容的cmdletbinding更低的方式去。

如果你想使用PowerShell腳本的cmdlet的附加功能,如參數屬性,參數設置等..然後用第二個去。

0

第一種形式是將一個或多個計算機名稱作爲參數列表或管道中的字符串參數。

第二種形式期待任一的字符串參數的陣列從一個參數列表,或從管道具有計算機名作爲屬性輸入對象。

1

要回答你的問題,我會說,第一種模式是剛剛從PowerShell 1.0中的遺留,也可以使用傳統的功能$input沒有處理腳本塊。至於你只是寫PowerShell 2.0的代碼,你可以忘記它。

關於管道的功能,在PowerShell中V1.0它們可以用filters處理。

,你只需要知道它已經這樣做了,當你從淨樣品或當你必須調試老Powerhell代碼。

個人我仍然使用我的模塊中的舊functionsfilters我保留cmdletbinding出口功能或配置文件功能。

Powershell有點像樂高積木,你可以用許多不同的方式做很多事情。

+0

你好。謝謝你的信息。這是我想知道的。 – lowteq 2012-03-08 23:06:12

2

不,第一個例子不僅僅是傳統。爲了創建一個使用數組參數並採用管道輸入的PowerShell函數,你必須做一些工作。

我甚至會說,第二個例子不起作用。至少我不能讓它工作。

取本示例...

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" } 
} 

結果...

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 

注意,當使用管道的$InputArray變量是5的單個值...

現在用BEGIN和PROCESS塊

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

    BEGIN 
    { 
     Write-Host 'BEGIN' 
     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" } 
    } 

    PROCESS 
    { 
     Write-Host 'PROCESS' 
     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" } 
    } 
} 

現在,這是會很奇怪

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這樣的例子,它實際上可以工作,但是它會運行foreach,並且有1個入口X次。或者如果你通過陣列,它會運行一次全套的foreach

所以我想技術上這個例子可以工作,但它可能不會按照你期望的方式工作。

另請注意,即使BEGIN塊沒有數據,該函數也會通​​過語法驗證。