PowerShell高级函数与对象输出全解析
立即解锁
发布时间: 2025-09-13 00:16:54 阅读量: 4 订阅数: 9 AIGC 

# PowerShell 高级函数与对象输出全解析
## 1. CmdletBinding 与通用参数
### 1.1 参数决策要点
在定义 PowerShell 函数的参数时,有几个关键决策点需要考虑:
- **$ComputerName**:设为必选参数是合理的。若未提供该参数值,PowerShell 会提示输入,若仍未提供则会报错。需注意,设为必选参数后,不能再为其提供默认值。
- **$LogFailuresToPath**:设为必选参数不合理,因为不应强制用户记录错误。可检查该参数是否提供,再相应启用日志记录。
- **$Protocol**:技术上是必选参数,但提供了默认值 "Wsman",所以无需强制用户手动提供值。
- **[switch] 参数**:不应设为必选,因为这本质上是强制其值为 $True。
- **必选参数数量**:可根据需要设置多个必选参数。
### 1.2 参数验证
$Protocol 参数存在缺陷,它可接受任意字符串。虽通过 If 结构可对错误值进行一定保护,但最好能完全避免接受错误值,并为用户提示有效取值。可通过添加 [ValidateSet()] 属性实现:
```powershell
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline=$True,
Mandatory=$True)]
[string[]]$ComputerName,
[string]$LogFailuresToPath,
[ValidateSet('Wsman','Dcom')]
[string]$Protocol = "Wsman",
[switch]$ProtocolFallback
)
```
添加该属性后,PowerShell 会禁止使用列表外的值,在自动生成的帮助中显示有效值,还能为用户提供选项卡补全功能。
### 1.3 参数别名
除使用 -ComputerName 作为参数名,还可添加别名,增加参数使用的灵活性:
```powershell
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline=$True,
Mandatory=$True)]
[Alias('CN','MachineName','Name')]
[string[]]$ComputerName,
[string]$LogFailuresToPath,
[ValidateSet('Wsman','Dcom')]
[string]$Protocol = "Wsman",
[switch]$ProtocolFallback
)
```
这里为 $ComputerName 参数定义了三个别名 -CN、-MachineName 和 -Name,它们都是有效的替代参数名。
### 1.4 支持 –Confirm 和 –WhatIf
[CmdletBinding()] 属性附带 -WhatIf 和 -Confirm 两个额外功能参数。以下是一个支持 ShouldProcess 的示例函数:
```powershell
Function Set-Something {
[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
Param(
)
} #function
```
若函数计划对系统进行更改,支持 ShouldProcess 是合适的。运行命令时:
- 若使用 -WhatIf,命令不会执行任何操作,仅显示会执行的内容。
- 若使用 -Confirm,PowerShell 会提示用户确认每个操作。
需注意,-WhatIf 和 -Confirm 开关会被函数内的命令继承。若要运行不支持这两个参数的命令,可使用 $PSCmdlet.ShouldProcess() 方法:
```powershell
Function Invoke-InfoTechExplosion {
[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Low')]
Param(
[Parameter(Mandatory=$True)]
[string[]]$DomainNameToCrash
)
ForEach ($Domain in $DomainNameToCrash) {
If ($PSCmdlet.ShouldProcess($Domain)) {
[System.Directory]::GetDomain($Domain).Destroy()
}
}
} #function
```
$PSCmdlet.ShouldProcess() 方法根据命令运行情况返回不同结果:
| 运行情况 | 返回结果 | 操作 |
| ---- | ---- | ---- |
| 未使用 -WhatIf 或 -Confirm | True | 执行 If 结构内的代码 |
| 使用 -WhatIf | False | 显示消息,不执行危险代码 |
| 使用 -Confirm | 根据用户响应返回 True 或 False | 根据返回结果决定是否执行危险代码 |
ConfirmImpact 设置与 shell 内置的 $ConfirmPreference 变量相关,默认值为 "High"。若 ConfirmImpact 等于或大于 $ConfirmPreference 的值,即使未显式输入 -Confirm 参数,也会自动使用。
### 1.5 最佳实践
- 可能修改系统的命令应支持 ShouldProcess 功能。通常,以 Get 为动词的命令无需支持,而 Set、Invoke、Remove、Add 等动词的命令应支持。
- 若声明支持 ShouldProcess,就必须实现该支持。需测试确保 -WhatIf 和 -Confirm 功能正常,避免因代码错误导致危险操作实际执行。
### 1.6 实践示例:改进 Set-TMServiceLogon 函数
#### 1.6.1 初始函数
```powershell
function Set-TMServiceLogon {
Param(
[string]$ServiceName,
[string[]]$ComputerName,
[string]$NewPassword,
[string]$NewUser,
[string]$ErrorLogFilePath
)
ForEach ($computer in $ComputerName) {
$option = New-CimSessionOption -Protocol Wsman
$session = New-CimSession -SessionOption $option `
-ComputerName $Computer
If ($PSBoundParameters.ContainsKey('NewUser')) {
$args = @{'StartName'=$NewUser;
'StartPassword'=$NewPassword}
} Else {
$args = @{'StartPassword'=$NewPassword}
}
Invoke-CimMethod -ComputerName $computer `
-MethodName Change `
-Query "SELECT * FROM Win32_Service WHERE Name = '$ServiceName'" `
-Arguments $args |
Select-Object -Property @{n='ComputerName';e={$computer}},
@{n='Result';e={$_.ReturnValue}}
$session | Remove-CimSession
} #foreach
} #function
```
#### 1.6.2 任务要求
将该函数改进为高级函数,需满足以下要求:
- 确保 ServiceName、ComputerName 和 NewPassword 为必选参数,NewUser 不为必选。
- 确保 ComputerName 可通过值接受管道输入。
- 确保 ServiceName、ComputerName、NewPassword 和 NewUser 可通过属性名接受管道输入。
#### 1.6.3 改进后的函数
```powershell
function Set-TMServiceLogon {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,
ValueFromPipelineByPropertyName=$True)]
[string]$ServiceName,
[Parameter(Mandatory=$True,
ValueFromPipelineByPropertyName=$True,
ValueFromPipeline=$True)]
[string[]]$ComputerName,
[Parameter(Mandatory=$True,
ValueFromPipelineByPropertyName=$True)]
[string]$NewPassword,
[Parameter(ValueFromPipelineByPropertyName=$True)]
[string]$NewUser,
[string]$ErrorLogFilePath
)
BEGIN{}
PROCESS{
ForEach ($computer in $ComputerName) {
$option = New-CimSessionOption -Protocol Wsman
$session = New-CimSession -SessionOption $option `
-ComputerName $Computer
If ($PSBoundParameters.ContainsKey('NewUser')) {
$args = @{'StartName'=$NewUser;
'StartPassword'=$NewPassword}
} Else {
$args = @{'StartPassword'=$NewPassword}
}
Invoke-C
```
0
0
复制全文
相关推荐









