Windows PowerShell: 的進階的功能生命週期

Windows PowerShell 的進階的功能,稱為 「 指令碼指令程式 — 過程上較為複雜,但以下是用來指示他們安裝和清除函式。

Don Jones

已有的學生一些我現場的 Windows PowerShell 類別的數字混淆的持續點。 我希望這裡有更詳細地瀏覽可協助回溯您一些混淆也。 主題是 Windows PowerShell,非正式稱為指令碼指令程式的進階的功能。 這種類型的函式的範本看起來像這樣:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN {} PROCESS {} END {} }

有幾個這些指令程式方面造成混淆。 例如,在這種沒有已定義的輸入的參數,呼叫的電腦名稱。 這可以接受來自管線的輸入。 這表示您可以在兩個不同的方式來呼叫此函式。 首先,您可以有字串輸送進去,例如從文字檔案,包含每行一個電腦名稱:

Get-Content names.txt | Do-Something

只要有一個或多個電腦名稱直接傳遞至參數,而且使用管線:

Do-Something –computername SERVER1,SERVER2

在第一個範例中,函式的開始區塊執行第一次。 然後,處理程序區塊的每個傳送中的電腦名稱執行一次。 $ 電腦名稱的變數會包含一次只能有一個電腦名稱。 最後,一旦所有正在處理它們,END 區塊執行一次。

在第二個範例中,BEGIN 和 END 區塊永遠不會執行。 處理程序區塊執行一次,以及 $ 電腦名稱包含每個已傳遞給參數的名稱。

很難進行設定,並在這兩種情況下執行的清除工作,可以讓行為極大的差異。 這可能會導致混淆處理,以 $ 電腦名稱的參數。 在第一個範例中只包含一個值一次,而在第二,它會包含一或多個值,取決於所給予的 –computername 參數。 您可以只將放在程序區塊 ForEach 迴圈解決 $ 電腦名稱的問題:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN {} PROCESS { Foreach ($computer in $computername) { # use $computer here } } END {} }

這項技術會保證,因此最好是使用,而非 $ 電腦名稱 $電腦變數會包含一次只有一個電腦名稱。

設定和清除工作會需要一點技巧。 您不想要直接在程序區塊中的設定。 當物件便會輸送在該區塊就可以執行多次。 相反地,您也不能直接將開始區塊放安裝程式。 如果沒有任何送入的不會執行的項目。 顯然有很多,無法處理的方式,但是這似乎是最好的:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN { $setup_done = $false function DoSomethingSetup { set-variable -name setup_done -value $true -scope 1 } DoSomethingSetup } PROCESS { if (-not $setup_done) { DoSomethingSetup } Foreach ($computer in $computername) { # use $computer here } } }

這會利用所有的 [開始]、 [處理程序] 和 [結束區塊共用通用的範圍,這表示它們都共用相同的變數。 藉由設定變數做為旗標,您可以確定開始區塊的機碼的內容 — 我的 DoSomethingSetup 函式,會呼叫一次。

請注意,"DoSomethingSetup"函式必須使用特殊的技術旗標設為 $True 一次您已經完成安裝工作。 因為它是一個函式時,DoSomethingSetup 會有自己的範圍。 通常,它無法變更從該範圍之外的某個變數的值。 您可以明確地修改使用此設定變數指令程式所需的變數。

正在清除工作執行相同的技巧,是比較困難一點。 在第一個範例中,位置物件正在傳送到執行某些動作,將會執行結束區塊。 您只可以那里將您的清除工作。 不過,在執行任何動作送入的第二個範例中,將不會執行結束。 處理程序區塊會僅執行一次,因此它不一定是 「 知道 」 END 區塊未執行。

您無法只需要呼叫 END 區塊中的函式的處理程序區塊。 處理程序區塊時,物件便會輸送中,會執行多次,而且您不想需要多次呼叫 END 區塊。

匿蹤一種方法解決問題,但是簡單的方法通常是最佳: 當您需要某種清理活動 (例如關閉資料庫連接) 時,忘了一併使用 BEGIN 和 END 區塊。 已假設它只會執行一次,並只將您所有的設定和清除工作該處的處理程序區塊。

它可以是有點浪費 — 可能開啟和關閉資料庫連接重複,例如 — 但有效。 它也不需要在程式碼中的怪異,硬遵循 perambulations 的需要。

程式設計來處理管線和非管線案例這些函式可能不容易。 在某些即將產生的資料行,我會共用某些其他同仁解決此問題,所以您需要在自己的環境中使用的不同選項的方式。

Denny Cherry

Don Jones 就是 Microsoft MVP 獎收件者的 「 了解 Windows PowerShell 中月的書籍"息 (Manning 的發行集安全,2010年),設計來幫助系統管理員會變得有效率地使用 Windows PowerShell 書籍作者。 先生也會提供公用及線上 Windows PowerShell 的訓練。 在他的網站透過網站與他聯絡 ConcentratedTech.com

相關內容