ฟังก์ชั่น
หากคุณกำลังเขียนบรรทัดเดียวหรือสคริปต์ของ PowerShell และพบว่าตัวเองมักจะต้องแก้ไขสคริปต์เหล่านี้สำหรับสถานการณ์ต่างๆ มีโอกาสที่ดีที่จะกลายเป็นตัวเลือกที่ดีที่จะกลายเป็นฟังก์ชันที่สามารถนำมาใช้ซ้ำได้
เมื่อใดก็ตามที่เป็นไปได้ ฉันชอบเขียนฟังก์ชันมากกว่าเพราะว่ามันเน้นเครื่องมือมากกว่า ฉันสามารถใส่ฟังก์ชันต่างๆ ในโมดูลสคริปต์ ใส่โมดูลนั้นใน $env:PSModulePath และเรียกใช้ฟังก์ชันต่างๆ โดยไม่จำเป็นต้องระบุตำแหน่งทางกายภาพที่บันทึกไว้ การใช้โมดูล PowerShellGet ทำให้การแบ่งปันโมดูลเหล่านั้นในพื้นที่เก็บข้อมูล NuGet เป็นเรื่องง่าย PowerShellGet มาพร้อมกับ PowerShell เวอร์ชัน 5.0 และสูงกว่า มีให้ดาวน์โหลดแยกต่างหากสำหรับ PowerShell เวอร์ชัน 3.0 และสูงกว่า
อย่าซับซ้อนเกินไป ทำให้มันเรียบง่ายและใช้วิธีที่ตรงไปตรงมาที่สุดในการทำงานให้สำเร็จ หลีกเลี่ยงนามแฝงและพารามิเตอร์ตำแหน่งในโค้ดใดๆ ที่คุณใช้ซ้ำ จัดรูปแบบโค้ดของคุณเพื่อให้อ่านง่าย อย่าฮาร์ดโค้ดค่า ใช้พารามิเตอร์และตัวแปร อย่าเขียนโค้ดที่ไม่จำเป็นถึงแม้ว่ามันจะไม่สร้างความเสียหายใดๆ ก็ตาม มันเพิ่มความซับซ้อนที่ไม่จำเป็น ความใส่ใจในรายละเอียดช่วยได้มากเมื่อเขียนโค้ด PowerShell
การตั้งชื่อ
เมื่อตั้งชื่อฟังก์ชันของคุณใน PowerShell ให้ใช้ชื่อตัวพิมพ์ Pascal พร้อมด้วยกริยาที่ได้รับอนุมัติและคำนามเอกพจน์ ฉันยังแนะนำให้เติมคำนำหน้าคำนามด้วย ตัวอย่างเช่น: <ApprovedVerb>-
ใน PowerShell มีรายการกริยาที่ได้รับการอนุมัติเฉพาะซึ่งสามารถรับได้โดยการเรียกใช้ Get-Verb
Get-Verb | Sort-Object -Property Verb
Verb Group
---- -----
Add Common
Approve Lifecycle
Assert Lifecycle
Backup Data
Block Security
Checkpoint Data
Clear Common
Close Common
Compare Data
Complete Lifecycle
Compress Data
Confirm Lifecycle
Connect Communications
Convert Data
ConvertFrom Data
ConvertTo Data
Copy Common
Debug Diagnostic
Deny Lifecycle
Disable Lifecycle
Disconnect Communications
Dismount Data
Edit Data
Enable Lifecycle
Enter Common
Exit Common
Expand Data
Export Data
Find Common
Format Common
Get Common
Grant Security
Group Data
Hide Common
Import Data
Initialize Data
Install Lifecycle
Invoke Lifecycle
Join Common
Limit Data
Lock Common
Measure Diagnostic
Merge Data
Mount Data
Move Common
New Common
Open Common
Optimize Common
Out Data
Ping Diagnostic
Pop Common
Protect Security
Publish Data
Push Common
Read Communications
Receive Communications
Redo Common
Register Lifecycle
Remove Common
Rename Common
Repair Diagnostic
Request Lifecycle
Reset Common
Resize Common
Resolve Diagnostic
Restart Lifecycle
Restore Data
Resume Lifecycle
Revoke Security
Save Data
Search Common
Select Common
Send Communications
Set Common
Show Common
Skip Common
Split Common
Start Lifecycle
Step Common
Stop Lifecycle
Submit Lifecycle
Suspend Lifecycle
Switch Common
Sync Data
Test Diagnostic
Trace Diagnostic
Unblock Security
Undo Common
Uninstall Lifecycle
Unlock Common
Unprotect Security
Unpublish Data
Unregister Lifecycle
Update Data
Use Other
Wait Lifecycle
Watch Common
Write Communications
ในตัวอย่างก่อนหน้านี้ ฉันได้จัดเรียงผลลัพธ์ตามคอลัมน์ กริยา คอลัมน์ กลุ่ม ช่วยให้คุณเข้าใจถึงวิธีการใช้คำกริยาเหล่านี้ สิ่งสำคัญคือต้องเลือกคำกริยาที่ได้รับอนุมัติใน PowerShell เมื่อมีการเพิ่มฟังก์ชันลงในโมดูล โมดูลจะสร้างข้อความเตือนเมื่อโหลดหากคุณเลือกกริยาที่ไม่ได้รับการอนุมัติ ข้อความเตือนนั้นทำให้ฟังก์ชันของคุณดูไม่เป็นมืออาชีพ กริยาที่ไม่ได้รับการอนุมัติยังจำกัดการค้นพบฟังก์ชันของคุณอีกด้วย
ฟังก์ชั่นง่ายๆ
ฟังก์ชันใน PowerShell ได้รับการประกาศโดยใช้คำสำคัญฟังก์ชัน ตามด้วยชื่อฟังก์ชัน จากนั้นจึงใช้เครื่องหมายปีกกาเปิดและปิด รหัสที่ฟังก์ชันจะดำเนินการจะอยู่ภายในเครื่องหมายปีกกาเหล่านั้น
function Get-Version {
$PSVersionTable.PSVersion
}
ฟังก์ชันที่แสดงเป็นตัวอย่างง่ายๆ ที่ส่งคืนเวอร์ชันของ PowerShell
Get-Version
Major Minor Build Revision
----- ----- ----- --------
5 1 14393 693
มีโอกาสสูงที่ชื่อจะขัดแย้งกับฟังก์ชันที่มีชื่อบางอย่างเช่น Get-Version และคำสั่งเริ่มต้นใน PowerShell หรือคำสั่งที่ผู้อื่นอาจเขียน นี่คือเหตุผลที่ฉันแนะนำให้นำหน้าส่วนนามของฟังก์ชันของคุณเพื่อช่วยป้องกันความขัดแย้งในการตั้งชื่อ ในตัวอย่างต่อไปนี้ ฉันจะใช้คำนำหน้า "PS"
function Get-PSVersion {
$PSVersionTable.PSVersion
}
นอกเหนือจากชื่อแล้ว ฟังก์ชันนี้ยังเหมือนกับฟังก์ชันก่อนหน้า
Get-PSVersion
Major Minor Build Revision
----- ----- ----- --------
5 1 14393 693
แม้ว่าจะขึ้นต้นคำนามด้วยคำอย่างเช่น PS แต่ก็ยังมีโอกาสสูงที่ชื่อจะขัดแย้งกัน ฉันมักจะนำหน้าคำนามฟังก์ชันของฉันด้วยชื่อย่อของฉัน พัฒนามาตรฐานและยึดมั่นกับมัน
function Get-MrPSVersion {
$PSVersionTable.PSVersion
}
ฟังก์ชันนี้ไม่แตกต่างจากสองฟังก์ชันก่อนหน้านี้ ยกเว้นการใช้ชื่อที่สมเหตุสมผลมากกว่าเพื่อพยายามป้องกันการขัดแย้งในการตั้งชื่อกับคำสั่ง PowerShell อื่นๆ
Get-MrPSVersion
Major Minor Build Revision
----- ----- ----- --------
5 1 14393 693
เมื่อโหลดลงในหน่วยความจำแล้ว คุณจะสามารถดูฟังก์ชันต่างๆ บน ฟังก์ชัน PSDrive ได้
Get-ChildItem -Path Function:\Get-*Version
CommandType Name Version Source
----------- ---- ------- ------
Function Get-Version
Function Get-PSVersion
Function Get-MrPSVersion
หากคุณต้องการลบฟังก์ชันเหล่านี้ออกจากเซสชันปัจจุบัน คุณจะต้องลบออกจาก ฟังก์ชัน PSDrive หรือปิดและเปิด PowerShell อีกครั้ง
Get-ChildItem -Path Function:\Get-*Version | Remove-Item
ตรวจสอบว่าฟังก์ชันถูกลบออกไปแล้วจริงๆ
Get-ChildItem -Path Function:\Get-*Version
หากฟังก์ชันถูกโหลดเป็นส่วนหนึ่งของโมดูล ก็สามารถยกเลิกการโหลดโมดูลเพื่อลบออกได้
Remove-Module -Name <ModuleName>
Remove-Module cmdlet จะลบโมดูลออกจากหน่วยความจำในเซสชัน PowerShell ปัจจุบันของคุณ แต่จะไม่ลบออกจากระบบของคุณหรือจากดิสก์
พารามิเตอร์
อย่ากำหนดค่าคงที่! ใช้พารามิเตอร์และตัวแปร เมื่อพูดถึงการตั้งชื่อพารามิเตอร์ของคุณ ให้ใช้ชื่อเดียวกันกับ cmdlets เริ่มต้นสำหรับชื่อพารามิเตอร์ของคุณทุกครั้งที่เป็นไปได้
function Test-MrParameter {
param (
$ComputerName
)
Write-Output $ComputerName
}
เหตุใดฉันจึงใช้ ชื่อคอมพิวเตอร์ และไม่ใช้ คอมพิวเตอร์, ชื่อเซิร์ฟเวอร์ หรือ โฮสต์ สำหรับชื่อพารามิเตอร์ของฉัน เป็นเพราะฉันต้องการให้ฟังก์ชันของฉันเป็นมาตรฐานเหมือน cmdlets เริ่มต้น
ฉันจะสร้างฟังก์ชันเพื่อสืบค้นคำสั่งทั้งหมดบนระบบและส่งกลับจำนวนคำสั่งที่มีชื่อพารามิเตอร์เฉพาะ
function Get-MrParameterCount {
param (
[string[]]$ParameterName
)
foreach ($Parameter in $ParameterName) {
$Results = Get-Command -ParameterName $Parameter -ErrorAction SilentlyContinue
[pscustomobject]@{
ParameterName = $Parameter
NumberOfCmdlets = $Results.Count
}
}
}
ดังที่คุณเห็นในผลลัพธ์ที่แสดงด้านล่าง 39 คำสั่งที่มีพารามิเตอร์ ชื่อคอมพิวเตอร์ ไม่มี cmdlet ใดที่มีพารามิเตอร์ เช่น คอมพิวเตอร์, ชื่อเซิร์ฟเวอร์, โฮสต์ หรือ เครื่อง
Get-MrParameterCount -ParameterName ComputerName, Computer, ServerName, Host, Machine
ParameterName NumberOfCmdlets
------------- ---------------
ComputerName 39
Computer 0
ServerName 0
Host 0
Machine 0
ฉันขอแนะนำให้ใช้ตัวพิมพ์เดียวกันกับชื่อพารามิเตอร์ของคุณเป็น cmdlets เริ่มต้น ใช้ ชื่อคอมพิวเตอร์ ไม่ใช่ ชื่อคอมพิวเตอร์ สิ่งนี้ทำให้ฟังก์ชันของคุณมีรูปลักษณ์และความรู้สึกเหมือนกับ cmdlets เริ่มต้น คนที่คุ้นเคยกับ PowerShell อยู่แล้วจะรู้สึกเหมือนอยู่บ้าน
คำสั่ง param ช่วยให้คุณสามารถกำหนดพารามิเตอร์ตั้งแต่หนึ่งตัวขึ้นไป คำจำกัดความของพารามิเตอร์คั่นด้วยเครื่องหมายจุลภาค (,) สำหรับข้อมูลเพิ่มเติม โปรดดู about_Functions_Advanced_Parameters
ฟังก์ชั่นขั้นสูง
การเปลี่ยนฟังก์ชันใน PowerShell ให้เป็นฟังก์ชันขั้นสูงนั้นง่ายมาก ความแตกต่างประการหนึ่งระหว่างฟังก์ชันและฟังก์ชันขั้นสูงก็คือ ฟังก์ชันขั้นสูงมีพารามิเตอร์ทั่วไปจำนวนหนึ่งที่จะถูกเพิ่มลงในฟังก์ชันโดยอัตโนมัติ พารามิเตอร์ทั่วไปเหล่านี้ประกอบด้วยพารามิเตอร์ เช่น Verbose และ Debug
ฉันจะเริ่มต้นด้วยฟังก์ชัน Test-MrParameter ที่ใช้ในหัวข้อที่แล้ว
function Test-MrParameter {
param (
$ComputerName
)
Write-Output $ComputerName
}
สิ่งที่ฉันต้องการให้คุณสังเกตคือฟังก์ชัน Test-MrParameter ไม่มีพารามิเตอร์ทั่วไป มีสองวิธีในการดูพารามิเตอร์ทั่วไป วิธีหนึ่งคือการดูไวยากรณ์โดยใช้ Get-Command
Get-Command -Name Test-MrParameter -Syntax
Test-MrParameter [[-ComputerName] <Object>]
อีกประการหนึ่งคือการเจาะลึกลงในพารามิเตอร์ด้วย Get-Command
(Get-Command -Name Test-MrParameter).Parameters.Keys
ComputerName
เพิ่ม CmdletBinding เพื่อเปลี่ยนฟังก์ชันให้เป็นฟังก์ชันขั้นสูง
function Test-MrCmdletBinding {
[CmdletBinding()] #<<-- This turns a regular function into an advanced function
param (
$ComputerName
)
Write-Output $ComputerName
}
การเพิ่ม CmdletBinding จะเพิ่มพารามิเตอร์ทั่วไปโดยอัตโนมัติ CmdletBinding จำเป็นต้องมีบล็อก param แต่บล็อก param สามารถเว้นว่างได้
Get-Command -Name Test-MrCmdletBinding -Syntax
Test-MrCmdletBinding [[-ComputerName] <Object>] [<CommonParameters>]
การเจาะลึกพารามิเตอร์ด้วย Get-Command จะแสดงชื่อพารามิเตอร์จริงรวมถึงชื่อทั่วไปด้วย
(Get-Command -Name Test-MrCmdletBinding).Parameters.Keys
ComputerName
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable
รองรับกระบวนการควร
SupportsShouldProcess เพิ่มพารามิเตอร์ WhatIf และ Confirm สิ่งเหล่านี้จำเป็นสำหรับคำสั่งที่ทำการเปลี่ยนแปลงเท่านั้น
function Test-MrSupportsShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param (
$ComputerName
)
Write-Output $ComputerName
}
โปรดสังเกตว่าขณะนี้มีพารามิเตอร์ WhatIf และ ยืนยัน
Get-Command -Name Test-MrSupportsShouldProcess -Syntax
Test-MrSupportsShouldProcess [[-ComputerName] <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]
อีกครั้ง คุณยังสามารถใช้ Get-Command เพื่อส่งคืนรายการชื่อพารามิเตอร์จริง รวมถึงชื่อทั่วไปพร้อมกับ WhatIf และ Confirm
(Get-Command -Name Test-MrSupportsShouldProcess).Parameters.Keys
ComputerName
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable
WhatIf
Confirm
การตรวจสอบพารามิเตอร์
ตรวจสอบอินพุตตั้งแต่เนิ่นๆ เหตุใดจึงอนุญาตให้โค้ดของคุณดำเนินต่อไปบนเส้นทางเมื่อไม่สามารถทำงานหากไม่มีอินพุตที่ถูกต้อง
พิมพ์ตัวแปรที่ใช้สำหรับพารามิเตอร์ของคุณเสมอ (ระบุประเภทข้อมูล)
function Test-MrParameterValidation {
[CmdletBinding()]
param (
[string]$ComputerName
)
Write-Output $ComputerName
}
ในตัวอย่างก่อนหน้านี้ ฉันได้ระบุ String เป็นประเภทข้อมูลสำหรับพารามิเตอร์ ComputerName ซึ่งทำให้อนุญาตให้ระบุชื่อคอมพิวเตอร์เครื่องเดียวเท่านั้น หากมีการระบุชื่อคอมพิวเตอร์มากกว่าหนึ่งชื่อผ่านรายการที่คั่นด้วยเครื่องหมายจุลภาค จะเกิดข้อผิดพลาดขึ้น
Test-MrParameterValidation -ComputerName Server01, Server02
Test-MrParameterValidation : Cannot process argument transformation on parameter
'ComputerName'. Cannot convert value to type System.String.
At line:1 char:42
+ Test-MrParameterValidation -ComputerName Server01, Server02
+
+ CategoryInfo : InvalidData: (:) [Test-MrParameterValidation], ParameterBindingArg
umentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Test-MrParameterValidation
ปัญหาเกี่ยวกับคำจำกัดความปัจจุบันคือสามารถละเว้นค่าของพารามิเตอร์ ชื่อคอมพิวเตอร์ ได้ แต่จำเป็นต้องมีค่าเพื่อให้ฟังก์ชันเสร็จสมบูรณ์ นี่คือจุดที่แอตทริบิวต์พารามิเตอร์ บังคับ มีประโยชน์
function Test-MrParameterValidation {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string]$ComputerName
)
Write-Output $ComputerName
}
ไวยากรณ์ที่ใช้ในตัวอย่างก่อนหน้านี้คือ PowerShell เวอร์ชัน 3.0 และเข้ากันได้สูงกว่า [Parameter(Mandatory=$true)] สามารถระบุแทนได้เพื่อทำให้ฟังก์ชันเข้ากันได้กับ PowerShell เวอร์ชัน 2.0 และสูงกว่า เมื่อจำเป็นต้องมี ชื่อคอมพิวเตอร์ แล้ว หากไม่มีการระบุ ฟังก์ชันจะแจ้งให้ระบุ
Test-MrParameterValidation
cmdlet Test-MrParameterValidation at command pipeline position 1
Supply values for the following parameters:
ComputerName:
หากคุณต้องการอนุญาตให้มีค่ามากกว่าหนึ่งค่าสำหรับพารามิเตอร์ ComputerName ให้ใช้ประเภทข้อมูล String แต่เพิ่มวงเล็บเหลี่ยมแบบเปิดและแบบปิดให้กับประเภทข้อมูลเพื่ออนุญาตให้มีอาร์เรย์ของสตริง .
function Test-MrParameterValidation {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string[]]$ComputerName
)
Write-Output $ComputerName
}
บางทีคุณอาจต้องการระบุค่าเริ่มต้นสำหรับพารามิเตอร์ ComputerName หากไม่ได้ระบุไว้ ปัญหาคือไม่สามารถใช้ค่าเริ่มต้นกับพารามิเตอร์บังคับได้ คุณจะต้องใช้แอตทริบิวต์การตรวจสอบความถูกต้องของพารามิเตอร์ ValidateNotNullOrEmpty ด้วยค่าเริ่มต้นแทน
function Test-MrParameterValidation {
[CmdletBinding()]
param (
[ValidateNotNullOrEmpty()]
[string[]]$ComputerName = $env:COMPUTERNAME
)
Write-Output $ComputerName
}
แม้จะตั้งค่าเริ่มต้น พยายามอย่าใช้ค่าคงที่ ในตัวอย่างก่อนหน้านี้ $env:COMPUTERNAME จะถูกใช้เป็นค่าเริ่มต้น ซึ่งจะถูกแปลเป็นชื่อคอมพิวเตอร์ในระบบโดยอัตโนมัติหากไม่มีการระบุค่า
เอาท์พุทแบบละเอียด
แม้ว่าความคิดเห็นแบบอินไลน์จะมีประโยชน์ โดยเฉพาะอย่างยิ่งหากคุณกำลังเขียนโค้ดที่ซับซ้อน ผู้ใช้จะไม่มีทางเห็นความคิดเห็นเหล่านั้นเลย เว้นแต่พวกเขาจะตรวจสอบในตัวโค้ดเอง
ฟังก์ชันที่แสดงในตัวอย่างต่อไปนี้มีความคิดเห็นแบบอินไลน์ในลูป foreach แม้ว่าความคิดเห็นเฉพาะนี้อาจค้นหาได้ไม่ยาก แต่ลองจินตนาการดูว่าฟังก์ชันมีโค้ดหลายร้อยบรรทัดหรือไม่
function Test-MrVerboseOutput {
[CmdletBinding()]
param (
[ValidateNotNullOrEmpty()]
[string[]]$ComputerName = $env:COMPUTERNAME
)
foreach ($Computer in $ComputerName) {
#Attempting to perform some action on $Computer <<-- Don't use
#inline comments like this, use write verbose instead.
Write-Output $Computer
}
}
ตัวเลือกที่ดีกว่าคือการใช้ Write-Verbose แทนความคิดเห็นแบบอินไลน์
function Test-MrVerboseOutput {
[CmdletBinding()]
param (
[ValidateNotNullOrEmpty()]
[string[]]$ComputerName = $env:COMPUTERNAME
)
foreach ($Computer in $ComputerName) {
Write-Verbose -Message "Attempting to perform some action on $Computer"
Write-Output $Computer
}
}
เมื่อเรียกใช้ฟังก์ชันโดยไม่มีพารามิเตอร์ Verbose เอาต์พุตแบบละเอียดจะไม่แสดง
Test-MrVerboseOutput -ComputerName Server01, Server02
เมื่อเรียกด้วยพารามิเตอร์ Verbose เอาต์พุตแบบละเอียดจะปรากฏขึ้น
Test-MrVerboseOutput -ComputerName Server01, Server02 -Verbose
อินพุตไปป์ไลน์
เมื่อคุณต้องการให้ฟังก์ชันของคุณยอมรับอินพุตไปป์ไลน์ จำเป็นต้องมีการเข้ารหัสเพิ่มเติมบางอย่าง ตามที่กล่าวไว้ก่อนหน้าในหนังสือเล่มนี้ คำสั่งสามารถรับอินพุตไปป์ไลน์ ตามค่า (ตามประเภท) หรือ ตามชื่อคุณสมบัติ คุณสามารถเขียนฟังก์ชันของคุณได้เหมือนกับคำสั่งเนทีฟ เพื่อให้ฟังก์ชันยอมรับอินพุตประเภทใดประเภทหนึ่งหรือทั้งสองประเภทก็ได้
หากต้องการยอมรับอินพุตไปป์ไลน์ ตามค่า ให้ระบุแอตทริบิวต์พารามิเตอร์ ValueFromPipeline สำหรับพารามิเตอร์นั้น ๆ โปรดทราบว่าคุณสามารถยอมรับอินพุตไปป์ไลน์ ตามค่า จากประเภทข้อมูลประเภทใดประเภทหนึ่งเท่านั้น ตัวอย่างเช่น หากคุณมีพารามิเตอร์สองตัวที่ยอมรับอินพุตสตริง มีเพียงตัวเดียวเท่านั้นที่ยอมรับอินพุตไปป์ไลน์ได้ ตามค่า เพราะหากคุณระบุไว้สำหรับพารามิเตอร์สตริงทั้งสอง อินพุตไปป์ไลน์จะไม่ทราบว่าพารามิเตอร์ใด สิ่งหนึ่งที่จะผูกมัด นี่เป็นอีกเหตุผลที่ฉันเรียกอินพุตไปป์ไลน์ประเภทนี้ว่า ตามประเภท แทนที่จะเป็น ตามค่า
อินพุตไปป์ไลน์มาทีละรายการคล้ายกับวิธีจัดการรายการต่างๆ ในลูป foreach อย่างน้อยที่สุด จำเป็นต้องมีบล็อก กระบวนการ เพื่อประมวลผลแต่ละรายการเหล่านี้ หากคุณยอมรับอาร์เรย์เป็นอินพุต หากคุณยอมรับเพียงค่าเดียวเป็นอินพุต ก็ไม่จำเป็นต้องบล็อก กระบวนการ แต่ฉันยังคงแนะนำให้ระบุเพื่อความสอดคล้องกัน
function Test-MrPipelineInput {
[CmdletBinding()]
param (
[Parameter(Mandatory,
ValueFromPipeline)]
[string[]]$ComputerName
)
PROCESS {
Write-Output $ComputerName
}
}
การยอมรับอินพุตไปป์ไลน์ ตามชื่อคุณสมบัติ จะคล้ายกันยกเว้นว่าระบุไว้ด้วยแอตทริบิวต์พารามิเตอร์ ValueFromPipelineByPropertyName และสามารถระบุให้กับพารามิเตอร์จำนวนเท่าใดก็ได้โดยไม่คำนึงถึงประเภทข้อมูล สิ่งสำคัญคือเอาต์พุตของคำสั่งที่กำลังไพพ์ต้องมีชื่อคุณสมบัติที่ตรงกับชื่อของพารามิเตอร์หรือนามแฝงพารามิเตอร์ของฟังก์ชันของคุณ
function Test-MrPipelineInput {
[CmdletBinding()]
param (
[Parameter(Mandatory,
ValueFromPipelineByPropertyName)]
[string[]]$ComputerName
)
PROCESS {
Write-Output $ComputerName
}
}
บล็อก BEGIN และ END เป็นทางเลือก BEGIN จะถูกระบุก่อนบล็อก PROCESS และใช้เพื่อดำเนินการเริ่มต้นใดๆ ก่อนที่จะได้รับรายการจากไปป์ไลน์ นี่เป็นสิ่งสำคัญที่ต้องเข้าใจ ค่าที่ส่งไปไม่สามารถเข้าถึงได้ในบล็อก BEGIN บล็อก END จะถูกระบุหลังบล็อก PROCESS และจะใช้สำหรับการล้างข้อมูลเมื่อรายการทั้งหมดที่มีการไปป์ได้รับการประมวลผลแล้ว
การจัดการข้อผิดพลาด
ฟังก์ชันที่แสดงในตัวอย่างต่อไปนี้จะสร้างข้อยกเว้นที่ไม่สามารถจัดการได้เมื่อไม่สามารถติดต่อกับคอมพิวเตอร์ได้
function Test-MrErrorHandling {
[CmdletBinding()]
param (
[Parameter(Mandatory,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[string[]]$ComputerName
)
PROCESS {
foreach ($Computer in $ComputerName) {
Test-WSMan -ComputerName $Computer
}
}
}
มีสองวิธีในการจัดการข้อผิดพลาดใน PowerShell Try/Catch เป็นวิธีที่ทันสมัยกว่าในการจัดการกับข้อผิดพลาด
function Test-MrErrorHandling {
[CmdletBinding()]
param (
[Parameter(Mandatory,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[string[]]$ComputerName
)
PROCESS {
foreach ($Computer in $ComputerName) {
try {
Test-WSMan -ComputerName $Computer
}
catch {
Write-Warning -Message "Unable to connect to Computer: $Computer"
}
}
}
}
แม้ว่าฟังก์ชันที่แสดงในตัวอย่างก่อนหน้านี้จะใช้การจัดการข้อผิดพลาด แต่ก็ยังสร้างข้อยกเว้นที่ไม่สามารถจัดการได้เนื่องจากคำสั่งไม่สร้างข้อผิดพลาดในการสิ้นสุด นี่เป็นสิ่งสำคัญที่ต้องเข้าใจด้วย ตรวจพบเฉพาะข้อผิดพลาดในการยกเลิกเท่านั้น ระบุพารามิเตอร์ ErrorAction ด้วย Stop เป็นค่าเพื่อเปลี่ยนข้อผิดพลาดที่ไม่ยุติให้กลายเป็นข้อผิดพลาดที่ยุติ
function Test-MrErrorHandling {
[CmdletBinding()]
param (
[Parameter(Mandatory,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[string[]]$ComputerName
)
PROCESS {
foreach ($Computer in $ComputerName) {
try {
Test-WSMan -ComputerName $Computer -ErrorAction Stop
}
catch {
Write-Warning -Message "Unable to connect to Computer: $Computer"
}
}
}
}
อย่าแก้ไขตัวแปร $ErrorActionPreference ส่วนกลาง เว้นแต่จะจำเป็นจริงๆ หากคุณใช้บางอย่างเช่น .NET โดยตรงจากภายในฟังก์ชัน PowerShell คุณจะไม่สามารถระบุ ErrorAction บนคำสั่งได้ ในสถานการณ์นั้น คุณอาจต้องเปลี่ยนตัวแปร $ErrorActionPreference โกลบอล แต่หากคุณเปลี่ยน ให้เปลี่ยนกลับทันทีหลังจากลองใช้คำสั่ง
ความช่วยเหลือตามความคิดเห็น
ถือเป็นแนวทางปฏิบัติที่ดีที่สุดในการเพิ่มความช่วยเหลือตามความคิดเห็นให้กับฟังก์ชันของคุณ เพื่อให้คนที่คุณแชร์ด้วยจะรู้วิธีใช้งาน
function Get-MrAutoStoppedService {
<#
.SYNOPSIS
Returns a list of services that are set to start automatically, are not
currently running, excluding the services that are set to delayed start.
.DESCRIPTION
Get-MrAutoStoppedService is a function that returns a list of services from
the specified remote computer(s) that are set to start automatically, are not
currently running, and it excludes the services that are set to start automatically
with a delayed startup.
.PARAMETER ComputerName
The remote computer(s) to check the status of the services on.
.PARAMETER Credential
Specifies a user account that has permission to perform this action. The default
is the current user.
.EXAMPLE
Get-MrAutoStoppedService -ComputerName 'Server1', 'Server2'
.EXAMPLE
'Server1', 'Server2' | Get-MrAutoStoppedService
.EXAMPLE
Get-MrAutoStoppedService -ComputerName 'Server1' -Credential (Get-Credential)
.INPUTS
String
.OUTPUTS
PSCustomObject
.NOTES
Author: Mike F Robbins
Website: http://mikefrobbins.com
Twitter: @mikefrobbins
#>
[CmdletBinding()]
param (
)
#Function Body
}
เมื่อคุณเพิ่มความช่วยเหลือตามความคิดเห็นไปยังฟังก์ชันของคุณ จะสามารถเรียกความช่วยเหลือสำหรับสิ่งเหล่านั้นได้เหมือนกับคำสั่งเริ่มต้นในตัว
ไวยากรณ์ทั้งหมดสำหรับการเขียนฟังก์ชันใน PowerShell อาจดูล้นหลาม โดยเฉพาะอย่างยิ่งสำหรับผู้ที่เพิ่งเริ่มต้น บ่อยครั้งหากฉันจำไวยากรณ์ของบางสิ่งบางอย่างไม่ได้ ฉันจะเปิดสำเนาที่สองของ ISE บนจอภาพแยกต่างหาก และดูตัวอย่างข้อมูล "Cmdlet (ฟังก์ชันขั้นสูง) - เสร็จสมบูรณ์" ขณะพิมพ์โค้ดสำหรับฟังก์ชันของฉัน คุณสามารถเข้าถึงตัวอย่างได้ใน PowerShell ISE โดยใช้คีย์ผสม Ctrl+J
สรุป
ในบทนี้ คุณได้เรียนรู้พื้นฐานของการเขียนฟังก์ชันใน PowerShell เพื่อรวมวิธีการเปลี่ยนฟังก์ชันให้เป็นฟังก์ชันขั้นสูง และองค์ประกอบที่สำคัญบางประการที่คุณควรพิจารณาเมื่อเขียนฟังก์ชัน PowerShell เช่น การตรวจสอบพารามิเตอร์ เอาต์พุตแบบละเอียด อินพุตไปป์ไลน์ การจัดการข้อผิดพลาด และความช่วยเหลือตามความคิดเห็น
ทบทวน
- คุณจะได้รับรายการกริยาที่ได้รับอนุมัติใน PowerShell ได้อย่างไร
- คุณจะเปลี่ยนฟังก์ชัน PowerShell ให้เป็นฟังก์ชันขั้นสูงได้อย่างไร
- เมื่อใดควรเพิ่มพารามิเตอร์ WhatIf และ ยืนยัน ให้กับฟังก์ชัน PowerShell ของคุณ
- คุณจะเปลี่ยนข้อผิดพลาดที่ไม่ยุติให้กลายเป็นข้อผิดพลาดที่ยุติได้อย่างไร
- เหตุใดคุณจึงควรเพิ่มความช่วยเหลือตามความคิดเห็นให้กับฟังก์ชันของคุณ
แนะนำให้อ่าน
- about_Functions
- about_Functions_Advanced_Parameters
- about_CommonParameters
- about_Functions_CmdletBindingAttribute
- about_Functions_ขั้นสูง
- about_Try_Catch_ในที่สุด
- about_Comment_Based_Help
- วิดีโอ: การสร้างเครื่องมือ PowerShell พร้อมฟังก์ชันขั้นสูงและโมดูลสคริปต์