about_Functions

簡短描述

描述如何在PowerShell中建立和使用函式。

詳細描述

函式是PowerShell語句的清單,其中包含您指派的名稱。 當您執行函式時,請輸入函式名稱。 清單中的語句會執行,就像您在命令提示字元中輸入它們一樣。

函式可以像:

function Get-PowerShellProcess { Get-Process PowerShell }

函式也可以和 Cmdlet 或應用程式一樣複雜。

如同 Cmdlet,函式可以有參數。 參數可以命名、位置、參數或動態參數。 您可以從命令列或管線讀取函式參數。

函式可以傳回可顯示、指派給變數或傳遞至其他函式或 Cmdlet 的值。 您也可以使用 return 關鍵詞來指定傳回值。 關鍵詞 return 不會影響或隱藏函式傳回的其他輸出。 不過,關鍵詞會在 return 該行結束函式。 如需詳細資訊,請參閱 about_Return

函式的語句清單可以包含不同類型的語句清單,其中包含關鍵詞 beginprocessendclean。 這些語句清單會以不同的方式處理來自管線的輸入。

filter 關鍵詞是用來建立在管線中每個物件上執行的函式類型。 篩選條件類似於具有區塊中所有語句的 process 函式。

函式也可以像 Cmdlet 一樣運作。 您可以建立與 Cmdlet 一樣運作的函式,而不需使用 C# 程序設計。 如需詳細資訊,請參閱 about_Functions_Advanced

重要

在腳本檔案和腳本型模組內,必須先定義函式,才能呼叫函式。

語法

以下是函式的語法:

function [<scope:>]<name> [([type]$parameter1[,[type]$parameter2])]
{
  begin {<statement list>}
  process {<statement list>}
  end {<statement list>}
  clean {<statement list>}
}
function [<scope:>]<name>
{
  param([type]$parameter1 [,[type]$parameter2])
  dynamicparam {<statement list>}
  begin {<statement list>}
  process {<statement list>}
  end {<statement list>}
  clean {<statement list>}
}

函式包含下列專案:

  • 關鍵詞function
  • 範圍(選擇性)
  • 您選取的名稱
  • 任何具名參數數目 (選擇性)
  • 一或多個以大括弧括住的 PowerShell 命令 {}

如需函式中關鍵詞和動態參數的詳細資訊 dynamicparam ,請參閱 about_Functions_Advanced_Parameters

輸入處理方法

本節所述的方法稱為輸入處理方法。 對於函式,這三種方法是由函式的 beginprocessend 區塊表示。 PowerShell 7.3 新增區塊 clean 進程方法。

您不需要在函式中使用任何這些區塊。 如果您沒有使用具名區塊,PowerShell 會將程式代碼 end 放入函式的 區塊中。 不過,如果您使用這些具名區塊中的任何一個 dynamicparam ,或定義區塊,則必須將所有程式代碼放在具名區塊中。

下列範例顯示函式的大綱,其中包含 begin 一次性前置處理區塊、 process 多個記錄處理的區塊,以及 end 一次性後置處理的區塊。

Function Test-ScriptCmdlet
{
[CmdletBinding(SupportsShouldProcess=$True)]
    Param ($Parameter1)
    begin{}
    process{}
    end{}
}

begin

此區塊可用來提供函式的選擇性一次性前置處理。 PowerShell 執行時間會針對管線中函式的每個實例使用此區塊中的程式代碼一次。

process

此區塊可用來提供函式的逐筆記錄處理。 您可以使用 process 區塊,而不定義其他區塊。 區塊執行的數目 process 取決於您如何使用 函式,以及函式所接收的輸入。

自動變數 $_$PSItem 包含管線中目前的物件,以用於 process 區塊。 自動 $input 變數包含只能供函式和腳本區塊使用的列舉值。 如需詳細資訊,請參閱 about_Automatic_Variables

  • 在管線開頭或外部呼叫函式時,會執行區塊 process 一次。
  • 在管線內,區塊 process 會針對到達函式的每個輸入對象執行一次。
  • 如果到達函式的管線輸入是空的,則 process 區塊 不會 執行。
    • beginendclean 區塊仍會執行。

重要

如果函式參數設定為接受管線輸入,且 process 未定義區塊,則逐筆記錄處理將會失敗。 在此情況下,不論輸入為何,您的函式只會執行一次。

end

此區塊可用來為函式提供選擇性的一次性後置處理。

clean

區塊 clean 已在PowerShell 7.3中新增。

區塊 clean 是方便使用者清除跨 beginprocessend 區塊的資源。 其語意類似於 finally 涵蓋腳本函式或腳本 Cmdlet 之所有其他具名區塊的區塊。 下列案例會強制執行資源清除:

  1. 當管線執行正常完成而不終止錯誤時
  2. 當管線執行因終止錯誤而中斷時
  3. 當管線停止時 Select-Object -First
  4. 當管線被 Ctrl+c 停止時, 或 StopProcessing()

警告

新增區塊 clean 是重大變更。 因為 clean 剖析為關鍵詞,所以會防止使用者直接呼叫名為 clean 的命令,做為腳本區塊中的第一個語句。 然而,這不太可能是個問題。 命令仍然可以使用呼叫運算符 (& clean) 來叫用。

簡單函式

函式不一定很複雜,才能有用。 最簡單的函式具有下列格式:

function <function-name> {statements}

例如,下列函式會使用 [以 管理員 istrator 執行] 選項啟動 PowerShell。

function Start-PSAdmin {Start-Process PowerShell -Verb RunAs}

若要使用 函式,請輸入: Start-PSAdmin

若要將語句新增至函式,請在個別行上輸入每個語句,或使用分號 ; 來分隔語句。

例如,下列函式會尋找目前用戶目錄中在開始日期之後變更的所有 .jpg 檔案。

function Get-NewPix
{
  $start = Get-Date -Month 1 -Day 1 -Year 2010
  $allpix = Get-ChildItem -Path $env:UserProfile\*.jpg -Recurse
  $allpix | Where-Object {$_.LastWriteTime -gt $Start}
}

您可以建立實用小型函式的工具箱。 將這些函式新增至 PowerShell 配置檔,如本主題的 about_Profiles 和更新版本所述。

函式名稱

您可以將任何名稱指派給函式,但您與其他函式共用的函式應遵循針對所有 PowerShell 命令所建立的命名規則。

函式名稱應該包含動詞名詞組,其中動詞會識別函式所執行的動作,而名詞會識別 Cmdlet 執行其動作的專案。

函式應該使用已針對所有 PowerShell 命令核准的標準動詞命令。 這些動詞可協助我們保持命令名稱一致且容易讓用戶瞭解。

如需標準 PowerShell 動詞的詳細資訊,請參閱 核准的動詞。

具有參數的函式

您可以搭配函式使用參數,包括具名參數、位置參數、參數參數和動態參數。 如需函式中動態參數的詳細資訊,請參閱 about_Functions_Advanced_Parameters

具名參數

您可以定義任意數目的具名參數。 您可以包含具名參數的預設值,如本主題稍後所述。

您可以使用 關鍵字在大括弧 param 內定義參數,如下列範例語法所示:

function <name> {
  param ([type]$parameter1 [,[type]$parameter2])
  <statement list>
}

您也可以在大括弧之外定義參數, Param 而不使用 關鍵詞,如下列範例語法所示:

function <name> [([type]$parameter1[,[type]$parameter2])] {
  <statement list>
}

以下是這個替代語法的範例。

function Add-Numbers([int]$one, [int]$two) {
    $one + $two
}

雖然慣用第一個方法,但這兩種方法之間並無差異。

當您執行函式時,您為參數提供的值會指派給包含參數名稱的變數。 該變數的值可以在函式中使用。

下列範例是稱為 Get-SmallFiles的函式。 此函式具有 $Size 參數。 函式會顯示小於 參數值 $Size 的所有檔案,並排除目錄:

function Get-SmallFiles {
  Param($Size)
  Get-ChildItem $HOME | Where-Object {
    $_.Length -lt $Size -and !$_.PSIsContainer
  }
}

在函式中,您可以使用 $Size 變數,這是為 參數定義的名稱。

若要使用此函式,請輸入下列命令:

Get-SmallFiles -Size 50

您也可以輸入具名參數的值,而不使用參數名稱。 例如,下列命令會提供與命名 Size 參數的命令相同的結果:

Get-SmallFiles 50

若要定義參數的預設值,請在參數名稱後面輸入等號和值,如下列範例的變化 Get-SmallFiles 所示:

function Get-SmallFiles ($Size = 100) {
  Get-ChildItem $HOME | Where-Object {
    $_.Length -lt $Size -and !$_.PSIsContainer
  }
}

如果您輸入 Get-SmallFiles 不含值,則函式會將 100 指派給 $size。 如果您提供值,函式會使用該值。

您可以選擇性地提供描述參數預設值的簡短說明字串,方法是將 PSDefaultValue 屬性新增至參數的描述,並指定 PSDefaultValueHelp 屬性。 若要提供說明字串,描述函式中 Get-SmallFiles Size 參數的預設值 (100),請新增 PSDefaultValue 屬性,如下列範例所示。

function Get-SmallFiles {
  param (
      [PSDefaultValue(Help = '100')]
      $Size = 100
  )
}

如需 PSDefaultValue 屬性類別的詳細資訊,請參閱 PSDefaultValue 屬性成員。

位置參數

位置參數是不含參數名稱的參數。 PowerShell 會使用參數值順序,將每個參數值與函式中的參數產生關聯。

當您使用位置參數時,請在函式名稱後面輸入一或多個值。 位置參數值會指派給 $args 陣列變數。 函式名稱後面的值會指派給陣列中的$args第一個位置。 $args[0]

下列 Get-Extension 函式會將 .txt 擴展名新增至您提供的檔案名:

function Get-Extension {
  $name = $args[0] + ".txt"
  $name
}
Get-Extension myTextFile
myTextFile.txt

參數參數

參數是不需要值的參數。 而是輸入函式名稱,後面接著 switch 參數的名稱。

若要定義 switch 參數,請在參數名稱之前指定類型 [switch] ,如下列範例所示:

function Switch-Item {
  param ([switch]$on)
  if ($on) { "Switch on" }
  else { "Switch off" }
}

當您在函式名稱後面輸入 On switch 參數時, 函式會顯示 Switch on。 如果沒有 switch 參數,它會顯示 Switch off

Switch-Item -on
Switch on
Switch-Item
Switch off

您也可以在執行函式時將布林值指派給參數,如下列範例所示:

Switch-Item -on:$true
Switch on
Switch-Item -on:$false
Switch off

使用 Splatting 代表命令參數

您可以使用曲線來代表命令的參數。 這項功能是在 Windows PowerShell 3.0 中引進的。

在呼叫會話中命令的函式中使用這項技術。 您不需要宣告或列舉命令參數,或在命令參數變更時變更函式。

下列範例函式會呼叫 Get-Command Cmdlet。 命令會使用 @Args 來表示 的參數 Get-Command

function Get-MyCommand { Get-Command @Args }

呼叫 函式時Get-MyCommand,您可以使用 的所有參數Get-Command。 參數和參數值會使用 @Args傳遞至命令。

Get-MyCommand -Name Get-ChildItem
CommandType     Name                ModuleName
-----------     ----                ----------
Cmdlet          Get-ChildItem       Microsoft.PowerShell.Management

@Args此功能會$Args使用自動參數,代表來自其餘自變數的未宣告 Cmdlet 參數和值。

如需詳細資訊,請參閱 about_Splatting

將物件管線傳送至函式

任何函式都可以從管線取得輸入。 您可以使用、processendclean 關鍵詞來控制函式如何處理管線begin的輸入。 下列範例語法顯示這些關鍵字:

process語句清單會針對管線中的每個物件執行一次。 process當區塊正在執行時,每個管線對象都會指派給$_自動變數,一次一個管線物件。

下列函式會使用 process 關鍵詞。 函式會顯示管線中的值:

function Get-Pipeline
{
  process {"The value is: $_"}
}

1,2,4 | Get-Pipeline
The value is: 1
The value is: 2
The value is: 4

如果您想要可從參數取得管線輸入或輸入的函式,則 process 區塊必須處理這兩種情況。 例如:

function Get-SumOfNumbers {
    param (
        [int[]]$Numbers
    )

    begin { $retValue = 0 }

    process {
        if ($null -ne $Numbers) {
           foreach ($n in $Numbers) {
               $retValue += $n
           }
        } else {
           $retValue += $_
        }
    }

    end { $retValue }
}

PS> 1,2,3,4 | Get-SumOfNumbers
10
PS> Get-SumOfNumbers 1,2,3,4
10

當您在管線中使用函式時,傳送至函式的物件會指派給 $input 自動變數。 函式會在任何對象來自管線之前,使用 begin 關鍵詞執行 語句。 函式會在從管線收到所有對象之後,使用 end 關鍵詞執行 語句。

下列範例顯示具有 beginend 關鍵詞的$input自動變數。

function Get-PipelineBeginEnd {
    begin   { "Begin: The input is $input" }
    end     { "End:   The input is $input" }
}

如果使用管線執行此函式,則會顯示下列結果:

1,2,4 | Get-PipelineBeginEnd
Begin: The input is
End:   The input is 1 2 4

begin當語句執行時,函式沒有來自管線的輸入。 語句 end 會在函式具有 值之後執行。

如果函式具有 process 關鍵字,則會從 $input 中移除 中的每個$input物件,並指派給 $_。 下列範例有 process 語句清單:

function Get-PipelineInput
{
    process {"Processing:  $_ " }
    end     {"End:   The input is: $input" }
}

在此範例中,傳送至函式的每個物件都會傳送至 process 語句清單。 語句 process 會在每個物件上執行,一次一個物件。 當函 $input 式到達 關鍵詞時,自動變數是空的 end

1,2,4 | Get-PipelineInput
Processing:  1
Processing:  2
Processing:  4
End:   The input is:

如需詳細資訊,請參閱 使用列舉值

PowerShell 7.3 已新增 區塊 clean 。 區塊clean是方便使用者清除、 processend 區塊中begin建立和使用的資源。 其語意類似於 finally 涵蓋腳本函式或腳本 Cmdlet 之所有其他具名區塊的區塊。 下列案例會強制執行資源清除:

  1. 當管線執行正常完成而不終止錯誤時
  2. 當管線執行因終止錯誤而中斷時
  3. 當管線停止時 Select-Object -First
  4. 當管線被 Ctrl+C 停止時, 或 StopProcessing()

警告

新增區塊 clean 是重大變更。 因為 clean 剖析為關鍵詞,所以會防止使用者直接呼叫名為 clean 的命令,做為腳本區塊中的第一個語句。 然而,這不太可能是個問題。 命令仍然可以使用呼叫運算符 (& clean) 來叫用。

篩選

篩選條件是在管線中每個物件上執行的函式類型。 篩選條件類似於具有區塊中所有語句的 process 函式。

篩選的語法如下所示:

filter [<scope:>]<name> {<statement list>}

下列篩選會從管線取得記錄專案,然後顯示整個專案或只顯示專案的訊息部分:

filter Get-ErrorLog ([switch]$Message)
{
  if ($Message) { Out-Host -InputObject $_.Message }
  else { $_ }
}

可用方式如下:

Get-WinEvent -LogName System -MaxEvents 100 | Get-ErrorLog -Message

函式範圍

函式存在於建立函式的範圍中。

如果函式是腳本的一部分,函式就可供該腳本內的語句使用。 根據預設,文稿中的函式無法在該腳本外部使用。

您可以指定函式的範圍。 例如,函式會新增至下列範例中的全域範圍:

function global:Get-DependentSvs {
  Get-Service | Where-Object {$_.DependentServices}
}

當函式位於全域範圍時,您可以在腳本、函式和命令行中使用 函式。

函式會建立新的範圍。 在函式中建立的專案,例如變數,只存在於函式範圍中。

如需詳細資訊,請參閱 about_Scopes

使用函式尋找和管理函式:磁碟驅動器

PowerShell 中的所有函式和篩選都會自動儲存在磁碟驅動器中 Function: 。 PowerShell 式提供者會公開此磁碟驅動器。

參考Function:磁碟驅動器時,請在 Function 後面輸入冒號,就像參考C電腦或D磁碟驅動器時所做的一樣。

下列命令會顯示 PowerShell 目前工作階段中的所有函式:

Get-ChildItem function:

函式中的命令會儲存為函式定義屬性中的腳本區塊。 例如,若要在 PowerShell 隨附的說明函式中顯示命令,請輸入:

(Get-ChildItem function:help).Definition

您也可以使用下列語法。

$function:help

如需磁碟驅動器的詳細資訊Function:,請參閱函式提供者的說明主題。 輸入 Get-Help Function

在新會話中重複使用函式

當您在PowerShell命令提示字元中輸入函式時,函式會變成目前會話的一部分。 函式可供使用,直到會話結束為止。

若要在所有 PowerShell 工作階段中使用您的函式,請將函式新增至 PowerShell 配置檔。 如需配置檔的詳細資訊,請參閱 about_Profiles

您也可以將函式儲存在PowerShell腳本檔案中。 在文本文件中輸入您的函式,然後使用擴展名儲存盤案 .ps1

撰寫函式的說明

Cmdlet Get-Help 會取得函式的說明,以及 Cmdlet、提供者和腳本的說明。 若要取得函式的說明,請輸入 Get-Help 後面接著函式名稱。

例如,若要取得函式的說明 Get-MyDisks ,請輸入:

Get-Help Get-MyDisks

您可以使用下列兩種方法之一來撰寫函式的說明:

  • 函式的批註型說明

    在批注中使用特殊關鍵詞建立說明主題。 若要為函式建立以批注為基礎的說明,批注必須放在函式主體的開頭或結尾,或放在函式關鍵詞前面的行上。 如需批注型說明的詳細資訊,請參閱 about_Comment_Based_Help

  • 以 XML 為基礎的函式說明

    建立 XML 型說明主題,例如通常針對 Cmdlet 建立的類型。 如果您要將說明主題當地語系化為多種語言,則需要 XML 型說明。

    若要將函式與 XML 型說明主題產生關聯,請使用 .EXTERNALHELP 以批注為基礎的說明關鍵詞。 如果沒有這個關鍵詞, Get-Help 則找不到函式說明主題,而對的函式只會 Get-Help 傳回自動產生的說明。

    如需 關鍵詞的詳細資訊 .EXTERNALHELP ,請參閱 about_Comment_Based_Help。 如需 XML 型說明的詳細資訊,請參閱 如何撰寫 Cmdlet 說明

另請參閱