函数
函数是可重用代码块的基本单元。PowerShell 函数支持参数定义、参数验证、管道输入等特性,是模块化编程的基础。
基本函数定义
使用 function 关键字定义函数:
function SayHello {
Write-Host "Hello, PowerShell!"
}
SayHello
带参数的函数:
function Greet {
param(
[string]$Name
)
Write-Host "Hello, $Name!"
}
Greet -Name "张三"
参数定义
基本参数
使用 param() 块定义参数:
function Add {
param(
[int]$a,
[int]$b
)
return $a + $b
}
Add -a 5 -b 3
默认参数值
function Greet {
param(
[string]$Name = "World"
)
Write-Host "Hello, $Name!"
}
Greet
Greet -Name "PowerShell"
位置参数
参数可以按位置传递:
function Add {
param(
[Parameter(Position=0)]
[int]$a,
[Parameter(Position=1)]
[int]$b
)
return $a + $b
}
Add 5 3
强制参数
使用 Mandatory 标记必填参数:
function Get-UserInfo {
param(
[Parameter(Mandatory=$true)]
[string]$Username,
[Parameter(Mandatory=$false)]
[int]$Age
)
Write-Host "用户: $Username, 年龄: $Age"
}
Get-UserInfo -Username "张三"
参数别名
为参数定义别名:
function Get-FileContent {
param(
[Parameter(Mandatory=$true)]
[Alias("Path", "File")]
[string]$FilePath
)
Get-Content $FilePath
}
Get-FileContent -Path "C:\test.txt"
Get-FileContent -File "C:\test.txt"
参数验证
PowerShell 提供多种参数验证属性:
ValidateSet:限制参数值为指定集合:
function Set-LogLevel {
param(
[ValidateSet("Debug", "Info", "Warning", "Error")]
[string]$Level
)
Write-Host "日志级别设置为: $Level"
}
Set-LogLevel -Level "Info"
Set-LogLevel -Level "Critical"
ValidateRange:限制数值范围:
function Set-Port {
param(
[ValidateRange(1, 65535)]
[int]$Port
)
Write-Host "端口: $Port"
}
Set-Port -Port 8080
Set-Port -Port 70000
ValidateLength:限制字符串长度:
function Set-Username {
param(
[ValidateLength(3, 20)]
[string]$Username
)
Write-Host "用户名: $Username"
}
ValidatePattern:正则表达式验证:
function Set-Email {
param(
[ValidatePattern("^\w+@\w+\.\w+$")]
[string]$Email
)
Write-Host "邮箱: $Email"
}
ValidateNotNullOrEmpty:不允许空值或空字符串:
function Process-Data {
param(
[ValidateNotNullOrEmpty()]
[string]$Data
)
Write-Host "处理数据: $Data"
}
ValidateScript:自定义验证脚本:
function Test-Path {
param(
[ValidateScript({
if (Test-Path $_) { $true }
else { throw "路径不存在: $_" }
})]
[string]$Path
)
Write-Host "有效路径: $Path"
}
返回值
return 语句
return 返回值并退出函数:
function Add {
param($a, $b)
return $a + $b
}
$result = Add 5 3
Write-Host $result
多返回值
函数可以返回多个值,实际返回的是数组:
function Get-MinMax {
param([int[]]$Numbers)
$min = $Numbers | Measure-Object -Minimum | Select-Object -ExpandProperty Minimum
$max = $Numbers | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum
return $min, $max
}
$result = Get-MinMax -Numbers 3, 1, 4, 1, 5, 9, 2, 6
Write-Host "最小值: $($result[0]), 最大值: $($result[1])"
输出到管道
函数中任何未捕获的输出都会进入管道:
function Get-Numbers {
1
2
3
}
Get-Numbers | ForEach-Object { $_ * 2 }
使用 Write-Output 显式输出:
function Get-Greeting {
Write-Output "Hello"
Write-Output "World"
}
禁止输出
使用 [void] 或 Out-Null 丢弃输出:
function Test-Function {
[void](Get-Process)
Get-Process | Out-Null
return "完成"
}
管道函数
管道输入
函数可以接收管道输入,使用 ValueFromPipeline 参数:
function Get-Doubled {
param(
[Parameter(ValueFromPipeline=$true)]
[int]$Number
)
process {
return $Number * 2
}
}
1..5 | Get-Doubled
begin、process、end 块
管道函数支持三个块:
function Measure-Text {
param(
[Parameter(ValueFromPipeline=$true)]
[string]$Text
)
begin {
$totalLength = 0
$count = 0
Write-Host "开始统计..."
}
process {
$totalLength += $Text.Length
$count++
Write-Host "处理: '$Text' (长度: $($Text.Length))"
}
end {
Write-Host "-------------------"
Write-Host "总条目: $count"
Write-Host "总长度: $totalLength"
Write-Host "平均长度: $([math]::Round($totalLength / $count, 2))"
}
}
"Hello", "PowerShell", "World" | Measure-Text
begin 块:管道开始前执行一次,用于初始化。
process 块:每个管道对象执行一次。
end 块:管道结束后执行一次,用于汇总。
管道输入属性名
从管道对象的属性获取值:
function Format-ProcessInfo {
param(
[Parameter(ValueFromPipelineByPropertyName=$true)]
[string]$Name,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[int]$Id
)
process {
Write-Host "进程: $Name (PID: $Id)"
}
}
Get-Process | Select-Object -First 5 | Format-ProcessInfo
高级函数
CmdletBinding 属性
添加 [CmdletBinding()] 使函数支持通用参数:
function Get-Data {
[CmdletBinding()]
param(
[string]$Name
)
Write-Verbose "正在获取 $Name 的数据..."
Write-Debug "调试信息"
return "数据: $Name"
}
Get-Data -Name "test" -Verbose
Get-Data -Name "test" -Debug
通用参数包括:
-Verbose:显示详细信息-Debug:显示调试信息-ErrorAction:错误处理方式-WarningAction:警告处理方式-ErrorVariable:存储错误的变量-OutVariable:存储输出的变量
SupportsShouldProcess
支持 -WhatIf 和 -Confirm 参数:
function Remove-OldFiles {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[string]$Path,
[int]$Days = 30
)
$cutoffDate = (Get-Date).AddDays(-$Days)
$files = Get-ChildItem $Path | Where-Object { $_.LastWriteTime -lt $cutoffDate }
foreach ($file in $files) {
if ($PSCmdlet.ShouldProcess($file.FullName, "删除文件")) {
Remove-Item $file.FullName -Force
Write-Host "已删除: $($file.FullName)"
}
}
}
Remove-OldFiles -Path "C:\Temp" -Days 7 -WhatIf
Remove-OldFiles -Path "C:\Temp" -Days 7 -Confirm
输出类型声明
使用 [OutputType()] 声明函数返回类型:
function Get-ServerInfo {
[OutputType([hashtable])]
[CmdletBinding()]
param(
[string]$ComputerName = $env:COMPUTERNAME
)
return @{
ComputerName = $ComputerName
OS = (Get-CimInstance Win32_OperatingSystem).Caption
CPU = (Get-CimInstance Win32_Processor).Name
Memory = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
}
}
函数作用域
局部变量
函数内定义的变量默认是局部的:
$x = 10
function Test-Scope {
$x = 20
Write-Host "函数内 x = $x"
}
Test-Scope
Write-Host "函数外 x = $x"
输出:
函数内 x = 20
函数外 x = 10
访问外部变量
使用 $script: 或 $global: 访问外部变量:
$counter = 0
function Increment-Counter {
$script:counter++
Write-Host "计数器: $counter"
}
Increment-Counter
Increment-Counter
Increment-Counter
作用域修饰符
| 修饰符 | 说明 |
|---|---|
$global: | 全局作用域 |
$script: | 脚本作用域 |
$local: | 当前作用域 |
$private: | 私有作用域 |
实用示例
日志函数
function Write-Log {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$Message,
[ValidateSet("Info", "Warning", "Error")]
[string]$Level = "Info",
[string]$LogFile = "C:\Logs\app.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "[$timestamp] [$Level] $Message"
switch ($Level) {
"Info" { Write-Host $logEntry -ForegroundColor Green }
"Warning" { Write-Host $logEntry -ForegroundColor Yellow }
"Error" { Write-Host $logEntry -ForegroundColor Red }
}
if (Test-Path (Split-Path $LogFile)) {
Add-Content -Path $LogFile -Value $logEntry
}
}
Write-Log -Message "服务启动成功" -Level "Info"
Write-Log -Message "磁盘空间不足" -Level "Warning"
Write-Log -Message "连接数据库失败" -Level "Error"
批量操作函数
function Invoke-BatchOperation {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string[]]$ComputerName,
[Parameter(Mandatory=$true)]
[scriptblock]$ScriptBlock,
[pscredential]$Credential
)
begin {
$results = @()
Write-Host "开始批量操作..."
}
process {
foreach ($computer in $ComputerName) {
if ($PSCmdlet.ShouldProcess($computer, "执行操作")) {
try {
$params = @{
ComputerName = $computer
ScriptBlock = $ScriptBlock
ErrorAction = "Stop"
}
if ($Credential) {
$params.Credential = $Credential
}
$result = Invoke-Command @params
$results += [PSCustomObject]@{
Computer = $computer
Status = "Success"
Result = $result
}
}
catch {
$results += [PSCustomObject]@{
Computer = $computer
Status = "Failed"
Result = $_.Exception.Message
}
}
}
}
}
end {
Write-Host "操作完成"
return $results
}
}
下一步
掌握了函数后,接下来学习 管道与对象,深入理解 PowerShell 的核心特性。