PowerShell 函数定义:function 与 param
在 PowerShell 脚本开发中,函数是模块化代码的核心工具。通过函数,你可以将重复逻辑封装为可复用的代码块。本文将详细介绍 PowerShell 中定义函数的两大核心关键字:function 和 param 的用法与区别。
一、function 关键字:函数的声明基础
function 是定义函数的基础关键字,它用于声明一个独立的代码块,给定函数名后即可被调用执行。
最简单的函数形式
一个最基本的 PowerShell 函数只需要 function 关键字加上函数名和一对大括号:
function Get-SystemInfo {
$os = Get-CimInstance -ClassName Win32_OperatingSystem
$computer = $env:COMPUTERNAME
$uptime = (Get-Date) - $os.LastBootUpTime
Write-Host "计算机名称: $computer"
Write-Host "操作系统: $($os.Caption)"
Write-Host "已运行时间: $($uptime.Days) 天 $($uptime.Hours) 小时"
}
调用这个函数时,直接输入函数名即可:
Get-SystemInfo
函数命名规范
PowerShell 函数名遵循动名词组合的命名约定,推荐使用「动词-名词」的形式,例如:
Get-ProcessStart-ServiceStop-ComputerNew-ItemRemove-File
这种命名方式让函数用途一目了然:Get- 表示获取信息,Start- 表示启动操作。
函数的作用域
默认情况下,在脚本中定义的函数仅在该脚本内部可用。如果希望在当前 PowerShell 会话中全局可用,需要使用 :Global 作用域修饰符:
function :Global:Invoke-Maintenance {
Write-Host "执行全局维护任务..."
}
二、param 关键字:参数定义的核心
param 是 PowerShell 中定义函数参数的标准方式。它位于函数体开头大括号之前,用于声明函数接受的输入参数。
基本参数定义
使用 param() 语法块定义参数,多个参数用逗号分隔:
function Send-Email {
param (
[string]$To,
[string]$Subject,
[string]$Body
)
Write-Host "正在发送邮件到: $To"
Write-Host "主题: $Subject"
Write-Host "内容: $Body"
}
调用时,按顺序传入参数:
Send-Email "admin@example.com" "系统警报" "服务器 CPU 使用率过高"
或者使用命名参数,顺序无关:
Send-Email -Subject "系统警报" -Body "服务器 CPU 使用率过高" -To "admin@example.com"
参数类型限制
通过在参数名前方括号中指定类型,可以限制参数的数据类型。如果传入类型不符,PowerShell 会自动尝试转换,转换失败则报错。
| 参数类型 | 用途 | 示例 |
|---|---|---|
[string] |
文本字符串 | $name` |
| `[int]` | 整数 | `$count |
[bool] |
真/假值 | $enabled` |
| `[array]` | 数组 | `$items |
[hashtable] |
键值对 | $settings` |
| `[datetime]` | 日期时间 | `$startDate |
function Calculate-Total {
param (
[int]$Quantity,
[decimal]$Price,
[string]$ProductName
)
$total = $Quantity * $Price
Write-Host "商品: $ProductName"
Write-Host "数量: $Quantity"
Write-Host "单价: $Price"
Write-Host "总价: $total"
}
可选参数与默认值
给参数赋值即可设置默认值,使参数变为可选。调用时不传入该参数时,使用默认值:
function New-User {
param (
[string]$Username,
[string]$Role = "User",
[bool]$Enabled = $true
)
Write-Host "创建用户: $Username"
Write-Host "角色: $Role"
Write-Host "启用状态: $Enabled"
}
```
**调用**时不传可选参数:
```powershell
New-User -Username "zhangsan"
```
### 参数属性增强
`param` 块支持多种属性修饰符,用于控制参数的行为:
```powershell
function Invoke-Operation {
param (
# 必填参数
[Parameter(Mandatory = $true)]
[string]$RequiredParam,
# 位置参数(可按位置传入)
[Parameter(Position = 0)]
[string]$FirstParam,
# 参数别名
[Alias("cn")]
[string]$ComputerName,
# 帮助消息
[string]$Description,
# 允许空值
[AllowNull()]
[string]$OptionalParam
)
Write-Host "必填参数: $RequiredParam"
Write-Host "位置参数: $FirstParam"
Write-Host "计算机名: $ComputerName"
}
三、两种参数定义方式的对比
在 PowerShell 中,function 关键字之后既可以使用 function 函数名 { 代码 } 语法,也可以在函数名后直接使用 param() 块。两种方式在功能上等效,但适用场景不同。
方式一:param() 块放函数内部
这是最常用也是推荐的方式,param() 放在函数体开头的位置:
function Install-Application {
param (
[string]$AppName,
[string]$Version = "latest"
)
Write-Host "正在安装 $AppName"
Write-Host "版本: $Version"
}
方式二:$args` 自动变量
对于简单的脚本函数,也可以不使用 `param`,而是通过 `$args 数组访问传入的参数:
function Show-Message {
Write-Host "第一个参数: $($args[0])"
Write-Host "第二个参数: $($args[1])"
Write-Host "参数总数: $($args.Count)"
}
调用:
Show-Message "Hello" "World"
两种方式的区别
| 特性 | param() 方式 | $args 方式 | |-----|-------------|-----------| | 参数命名 | 支持 | 不支持 | | 类型限制 | 支持 | 不支持 | | Mandatory 属性 | 支持 | 不支持 | | 别名 | 支持 | 不于持 | | 参数验证 | 支持 | 不支持 | | 代码可读性 | 高 | 低 | 对于生产环境,**强烈建议使用 `param()` 方式**,因为它提供了完整的参数控制能力。 --- ## 四、高级参数用法 ### 参数验证属性 PowerShell 提供了丰富的参数验证属性,确保传入参数符合预期: ```powershell function Process-Data { param ( # 值必须在指定范围内 [ValidateRange(1, 100)] [int]$Count,
# 值必须在枚举列表中
[ValidateSet("Low", "Medium", "High")]
[string]$Priority,
# 字符串长度范围
[ValidateLength(3, 20)]
[string]$Name,
# 正则表达式验证
[ValidatePattern("^\d{4}-\d{2}-\d{2}$")]
[string]$Date,
# 参数数量验证
[ValidateCount(1, 5)]
[array]$Items
)
Write-Host "Count: $Count"
Write-Host "Priority: $Priority"
Write-Host "Name: $Name"
Write-Host "Date: $Date"
Write-Host "Items: $($Items -join ', ')"
}
```
### 管道输入支持
让函数能够接收管道数据,需要使用 `ValueFromPipeline` 属性:
```powershell
function Format-Text {
param (
[Parameter(ValueFromPipeline = $true)]
[string]$InputText,
[string]$Prefix = "[INFO]",
[string]$Suffix = ""
)
process {
"$Prefix $InputText $Suffix"
}
}
**调用**:
```powershell
"第一行" | Format-Text -Suffix "(已处理)"
"第二行" | Format-Text -Prefix "[WARN]"
切换参数
使用 [switch] 类型定义布尔型切换参数,无需传入值:
function Backup-Files {
param (
[string]$Source,
[string]$Destination,
[switch]$Compress,
[switch]$Force,
[switch]$Verbose
)
Write-Host "源目录: $Source"
Write-Host "目标目录: $Destination"
Write-Host "压缩: $Compress"
Write-Host "强制覆盖: $Force"
Write-Host "详细模式: $Verbose"
}
调用:
Backup-Files -Source "C:\Data" -Destination "D:\Backup" -Compress -Force
五、完整函数示例
以下是一个综合运用 function 和 param 的完整示例,展示了一个生产级别的日志函数:
function Write-LogMessage {
param (
[Parameter(Mandatory = $true)]
[string]$Message,
[Parameter(Mandatory = $false)]
[ValidateSet("Info", "Warning", "Error", "Debug")]
[string]$Level = "Info",
[Parameter(Mandatory = $false)]
[string]$Source = "Script",
[Parameter(Mandatory = $false)]
[switch]$WriteToFile,
[Parameter(Mandatory = $false)]
[string]$LogFile = "C:\Logs\app.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "[$timestamp] [$Level] [$Source] $Message"
# 输出到控制台
switch ($Level) {
"Error" { Write-Host $logEntry -ForegroundColor Red }
"Warning" { Write-Host $logEntry -ForegroundColor Yellow }
"Debug" { Write-Host $logEntry -ForegroundColor Gray }
default { Write-Host $logEntry }
}
# 可选:写入文件
if ($WriteToFile) {
$logEntry | Out-File -FilePath $LogFile -Append -Encoding UTF8
}
return $logEntry
}
```
---
## 六、常见错误与调试
### 参数未传递导致的错误
当参数定义为必填但调用时未传递,会触发参数绑定失败错误:
```powershell
function Test-Function {
param (
[Parameter(Mandatory = $true)]
[string]$Required
)
Write-Host $Required
}
错误信息:Missing an argument for parameter 'Required'. Specify a parameter and try again.
参数类型不匹配
传入类型与声明类型不符时,PowerShell 尝试自动转换,失败则报错:
function Add-Numbers {
param ([int]$A, [int]$B)
$A + $B
}
调用 Add-Numbers -A "abc" -B 5 会报错,因为字符串无法转换为整数。
调试参数
在函数开头添加断点调试参数值:
function Debug-Function {
param ($Name, $Value)
Write-Host "函数被调用"
Write-Host "参数 Name: $Name"
Write-Host "参数 Value: $Value"
}
七、最佳实践总结
定义 PowerShell 函数时,遵循以下原则可以写出高质量、可维护的代码:
使用 function 关键字时,函数名采用「动词-名词」的 PascalCase 命名规范,使代码自文档化。将 param() 块放在函数体开头,保持结构清晰。参数尽量声明具体类型,便于类型检查和 IDE 智能提示。
使用 param 关键字时,必填参数使用 Mandatory = $true 属性并提供清晰的帮助消息。可选参数设置合理的默认值。使用 ValidateSet、ValidateRange 等属性进行输入验证。复杂函数支持管道输入以增强灵活性。

暂无评论,快来抢沙发吧!