簡短描述
描述如何在PowerShell中建立和使用函式。
完整描述
函式是PowerShell語句的清單,其中包含您指派的名稱。 當您執行函式時,請輸入函式名稱。
PowerShell 定義兩種函式:
-
函式是可依名稱呼叫的程式代碼區塊。 它可以接受輸入並傳回輸出。 函式是使用
function關鍵詞來定義。 -
篩選是一種函式,其設計目的是要處理管線中的數據。 篩選條件是使用
filter關鍵詞來定義。
您可以將函式中的語句分組為四個不同的預先定義腳本區塊之一。 這些文稿區塊是使用 關鍵詞 begin、 process、 end和 clean來命名。 如果您沒有使用這些關鍵詞,PowerShell 會將 語句放入適當的程式代碼區塊中。
函式也可以像 Cmdlet 一樣運作。 您可以建立與 Cmdlet 一樣運作的函式,而不需使用 C# 程序設計。 如需詳細資訊,請參閱 about_Functions_Advanced。
重要
在腳本檔案和腳本型模組內,必須先定義函式,才能呼叫函式。
函數語法
函式是使用下列語法來定義:
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 語句
{}
如果您未在定義中使用其中一個關鍵字 (begin、 、 processendclean) ,PowerShell 會將 語句放在 區塊中。functionend
如需函式中關鍵詞和動態參數的詳細資訊 dynamicparam ,請參閱 about_Functions_Advanced_Parameters。
函式可能很簡單:
function Get-PowerShellProcess { Get-Process pwsh }
定義函式之後,您就可以像內建 Cmdlet 一樣使用它。 例如,若要呼叫新定義的 Get-PowerShellProcess 函式:
Get-PowerShellProcess
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
110 78.72 172.39 10.62 10936 1 pwsh
函式也可以和 Cmdlet 一樣複雜。
函式可以傳回可顯示、指派給變數或傳遞至其他函式或 Cmdlet 的值。 您可以使用 return 關鍵詞傳回輸出。 關鍵詞 return 不會影響或隱藏函式傳回的其他輸出。 不過,關鍵詞會在 return 該行結束函式。 如需詳細資訊,請參閱 about_Return。
篩選語法
函式的 filter 意圖是提供定義在管線中每個物件上執行的函式的速記方式。
篩選的語法如下所示:
filter [<scope:>]<name> {<statement list>}
若要簡化函式的filter語法,請省略腳本區塊關鍵詞 (begin、 、 、 processendclean)。 PowerShell 會將 語句放在 區塊中 process 。 您可以在篩選函式中使用任何其他區塊,但意圖是提供定義函式的速記方式,該函式具有處理管線中每個物件的唯一用途。
下列篩選會從管線取得記錄專案,然後顯示整個專案或只顯示專案的訊息部分:
filter Get-EventMessage ([switch]$MessageOnly) {
if ($MessageOnly) { Out-Host -InputObject $_.Message }
else { $_ }
}
可用方式如下:
Get-WinEvent -LogName System -MaxEvents 100 | Get-EventMessage -MessageOnly
輸入處理方式
本節所述的方法稱為輸入處理方法。 針對函式,這三個方法會使用 函式的 begin、 process和 end 區塊來命名。 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。
- 如果未使用管線輸入來叫用函式,PowerShell 只會執行區塊
process一次。 - 在管線內,區塊
process會針對到達函式的每個輸入對象執行一次。 - 如果到達函式的管線輸入是空的,則
process區塊不會執行。-
begin、end和clean區塊仍會執行。
-
重要
如果函式參數接受管線輸入,且 process 未定義區塊,則逐筆記錄處理會失敗。 在此情況下,不論輸入為何,您的函式只會執行一次。
end
使用此區塊為函式提供選擇性的一次性後置處理。
clean
區塊 clean 已在PowerShell 7.3中新增。
區塊 clean 是方便使用者清除跨 begin、 process和 end 區塊的資源。 其語意類似於 finally 涵蓋腳本函式或腳本 Cmdlet 之所有其他具名區塊的區塊。 下列案例會強制執行資源清除:
- 當管線執行完成而不終止錯誤時
- 當管線執行因終止錯誤而中斷時
- 截斷管線時,例如:
Select-Object -First - 當管線由 Ctrl+c 停止或
StopProcessing()
清除區塊會捨棄寫入 成功 數據流的任何輸出。
警告
新增區塊 clean 是重大變更。 因為 clean 剖析為關鍵詞,所以會防止使用者直接呼叫名為 clean 的命令,做為腳本區塊中的第一個語句。 然而,這不太可能是個問題。 您仍然可以使用呼叫運算子 (& clean) 叫用命令。
簡單的功能
函式不一定很複雜,才能有用。 最簡單的函式具有下列格式:
function <function-name> { statements }
例如,下列函式會使用 [ 以系統管理員 身分執行] 選項啟動 PowerShell。
function Start-PSAdmin { Start-Process PowerShell -Verb RunAs }
若要使用 函式,請輸入: Start-PSAdmin
若要將 語句新增至函式,請在個別行上輸入每個語句,或使用分號 (;) 來分隔 語句。
例如,下列函式會尋找目前用戶目錄中在開始日期之後變更的所有 .jpg 檔案。
function Get-NewPicture {
$start = Get-Date -Month 1 -Day 1 -Year 2010
$allPics = Get-ChildItem -Path $Env:USERPROFILE\*.jpg -Recurse
$allPics | 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 屬性新增至參數的描述,並指定 PSDefaultValue 的 Help 屬性。 若要提供說明字串,描述函式中 SizeGet-SmallFiles預設值 (100),請新增 PSDefaultValue 屬性,如下列範例所示。
function Get-SmallFiles {
param (
[PSDefaultValue(Help = '100')]
$Size = 100
)
Get-ChildItem $HOME | Where-Object {
$_.Length -lt $Size -and !$_.PSIsContainer
}
}
如需 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-Command,您可以使用 的所有參數Get-MyCommand。 參數和參數值會使用 @args傳遞至命令。
Get-MyCommand -Name Get-ChildItem
CommandType Name ModuleName
----------- ---- ----------
Cmdlet Get-ChildItem Microsoft.PowerShell.Management
@args此功能會$args使用自動參數,代表來自其餘自變數的未宣告 Cmdlet 參數和值。
如需詳細資訊,請參閱 about_Splatting。
將物件管道化至函數
任何函式都可以從管線取得輸入。 您可以使用、begin、 process和 end 關鍵詞來控制函式如何處理管線clean的輸入。 下列範例語法顯示這些關鍵字:
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 ($MyInvocation.ExpectingInput) {
"Pipeline input: $_"
$retValue += $_
} else {
foreach ($n in $Numbers) {
"Command line input: $n"
$retValue += $n
}
}
}
end { "Sum = $retValue" }
}
PS> 1,2,3,4 | Get-SumOfNumbers
Pipeline input: 1
Pipeline input: 2
Pipeline input: 3
Pipeline input: 4
Sum = 10
PS> Get-SumOfNumbers 1,2,3,4
Command line input: 1
Command line input: 2
Command line input: 3
Command line input: 4
Sum = 10
當您在管線中使用函式時,傳送至函式的物件會指派給 $input 自動變數。 函式會在任何對象來自管線之前, begin 使用腳本區塊執行語句。 當管線中沒有其他物件時, end 函式會使用腳本區塊執行語句。
下列範例顯示$input用於和 begin 腳本區塊的end自動變數。
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是方便使用者清除、 begin和 process 區塊中end建立和使用的資源。 其語意類似於 finally 涵蓋腳本函式或腳本 Cmdlet 之所有其他具名區塊的區塊。 下列案例會強制執行資源清除:
- 當管線執行正常完成而不終止錯誤時
- 當管線執行因終止錯誤而中斷時
- 截斷管線時,例如:
Select-Object -First - 當管線由 Ctrl+C 停止時,或
StopProcessing()
警告
新增區塊 clean 是重大變更。 因為 clean 剖析為關鍵詞,所以會防止使用者直接呼叫名為 clean 的命令,做為腳本區塊中的第一個語句。 然而,這不太可能是個問題。 命令仍然可以使用呼叫運算符 (& clean) 來叫用。
功能範圍
函式存在於您建立函式的範圍中。
如果函式是腳本的一部分,函式就可供該腳本內的語句使用。 根據預設,文稿中的函式無法在該腳本外部使用。
您可以指定函式的範圍。 例如,函式會新增至下列範例中的全域範圍:
function Global:Get-DependentSvs {
Get-Service | Where-Object {$_.DependentServices}
}
當函式位於全域範圍時,您可以在腳本、函式和命令行中使用 函式。
函式會建立新的範圍。 在函式中建立的專案,例如變數,只存在於函式範圍中。
如需詳細資訊,請參閱 about_Scopes。
使用磁碟機尋找 Function: 和管理功能
PowerShell 中的所有函式和篩選都會自動儲存在磁碟驅動器中 Function: 。 PowerShell 函 式提供者會公開此磁碟驅動器。
參考Function:磁碟驅動器時,請在 Function 後面輸入冒號,就像參考C電腦或D磁碟驅動器時所做的一樣。
下列命令會顯示 PowerShell 目前工作階段中的所有函式:
Get-ChildItem Function:
函式中的命令會儲存為函式定義屬性中的腳本區塊。 例如,若要在 PowerShell 隨附的說明函式中顯示命令,請輸入:
(Get-ChildItem Function:help).Definition
您也可以使用下列語法。
$Function:help
如需詳細資訊,請參閱 about_Function_Provider。
在新工作階段中重複使用函數
當您在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 型說明。 若要將函式與 XML 型說明檔產生關聯,請使用
.EXTERNALHELP以批注為基礎的說明關鍵詞。 如果沒有這個關鍵詞,Get-Help找不到函式說明檔,而且只會傳回自動產生的說明。如需 關鍵詞的詳細資訊
.EXTERNALHELP,請參閱 about_Comment_Based_Help。 如需 XML 型說明的詳細資訊,請參閱 如何撰寫 Cmdlet 說明。