第22章笔记|把“可传参脚本”打磨成“高级好用的工具”
第22章笔记|把“可传参脚本”打磨成“高级好用的工具”
这章的核心:把一个能跑的脚本,升级成“可传参、可校验、可提示、可静默/可啰嗦、可二次加工输出”的高级脚本。关键只需几步:用对象做输出、用 param
声明参数、用 [CmdletBinding()]
开启高级特性,再加上参数校验与 Write-Verbose
友好提示。
一、为什么先用 Select-Object 而不是 Format-Table
-
Format-Table
只为“眼睛”服务,输出是文本,难以再加工。 -
Select-Object
输出对象,后续能随手:… | Format-Table
随看随排版… | Export-Csv
直接导出报表… | ConvertTo-Json
进系统对接
结论:脚本本体输出对象,把“长相”(格式化)留给调用者。
二、起点脚本(对象化输出)
<#
.SYNOPSIS
Get-DiskInventory:获取一台或多台计算机的逻辑磁盘信息。
.DESCRIPTION
使用 WMI 的 Win32_LogicalDisk,返回盘符、可用空间、总大小、可用率等对象属性。
.PARAMETER ComputerName
要查询的计算机名(可多个)。默认 localhost。
.PARAMETER DriveType
驱动器类型。参见 Win32_LogicalDisk 文档;3=本地磁盘(默认)。
.EXAMPLE
.\Get-DiskInventory.ps1 -ComputerName SERVER-R2 -DriveType 3
#>
param($ComputerName = 'localhost',$DriveType = 3
)Get-WmiObject -Class Win32_LogicalDisk -ComputerName $ComputerName -Filter "DriveType=$DriveType" |Sort-Object DeviceID |Select-Object DeviceID,@{Name='FreeSpace(MB)'; Expression = { [int]($_.FreeSpace/1MB) }},@{Name='Size(GB)'; Expression = { [int]($_.Size/1GB) }},@{Name='%Free'; Expression = { [int](($_.FreeSpace/$_.Size)*100) }}
三、加一行,变“高级脚本”
在脚本最前面加上:
[CmdletBinding()]
效果立显:
- 获得通用参数:
-Verbose
、-ErrorAction
、-WhatIf
等(视脚本逻辑而定) Write-Verbose
等流被正确管理- 更接近 Cmdlet 的体验
四、把参数做“对”:强制输入 + 类型约束 + 别名 + 校验
- 强制输入(用户不提供就提示)
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string] $ComputerName,[int] $DriveType = 3
)
- 友好提示(某些宿主会显示)
[Parameter(Mandatory=$true, HelpMessage='请输入要查询的计算机名')]
[string] $ComputerName
- 参数别名(照顾使用习惯)
[Alias('HostName')]
[string] $ComputerName
- 限定可选值(防错最有效)
[ValidateSet(2,3)] # 2=可移动盘, 3=本地盘
[int] $DriveType = 3
- 更多常用校验(按需选用)
[ValidateRange(1,100)]
[ValidatePattern('^\w+$')]
[ValidateNotNullOrEmpty()]
[ValidateScript({ Test-Connection $_ -Count 1 -Quiet })]
五、让脚本“会说话”:Write-Verbose
Write-Verbose "正在查询 $ComputerName 的磁盘清单(DriveType=$DriveType)"
# …执行查询…
Write-Verbose "查询完成"
调用时:
- 静默:
.\Get-DiskInventory.ps1 -ComputerName SRV1
- 啰嗦:
.\Get-DiskInventory.ps1 -ComputerName SRV1 -Verbose
六、整合后的“高质量可传参脚本”
<#
.SYNOPSIS
获取逻辑磁盘清单(对象输出)。
.DESCRIPTION
查询 Win32_LogicalDisk,返回盘符、可用空间、总大小与可用率;输出为对象,便于二次处理。
.PARAMETER ComputerName
目标计算机名(可单值/数组)。必填。
.PARAMETER DriveType
驱动器类型,仅支持 2(可移动)、3(本地)。默认 3。
.EXAMPLE
.\Get-DiskInventory.ps1 -ComputerName SERVER-R2 -DriveType 3 | Format-Table
.EXAMPLE
.\Get-DiskInventory.ps1 -ComputerName web1,web2 -Verbose | Export-Csv disks.csv -NoTypeInformation
#>
[CmdletBinding()]
param([Parameter(Mandatory=$true, HelpMessage='请输入要查询的计算机名')][Alias('HostName')][string[]] $ComputerName,[ValidateSet(2,3)][int] $DriveType = 3
)foreach ($comp in $ComputerName) {Write-Verbose "[$comp] 开始查询(DriveType=$DriveType)"Get-WmiObject -Class Win32_LogicalDisk -ComputerName $comp -Filter "DriveType=$DriveType" |Sort-Object DeviceID |Select-Object @{Name='ComputerName'; Expression={ $comp }},DeviceID,@{Name='FreeSpace(MB)'; Expression = { [int]($_.FreeSpace/1MB) }},@{Name='Size(GB)'; Expression = { [int]($_.Size/1GB) }},@{Name='%Free'; Expression = { [int]([math]::Round(($_.FreeSpace/$_.Size)*100,0)) }}Write-Verbose "[$comp] 查询完成"
}
七、使用示例(对象先行,随取随用)
- 只看表格:
.\Get-DiskInventory.ps1 -ComputerName SRV1 -Verbose | Format-Table
- 导成 CSV 报表:
.\Get-DiskInventory.ps1 -ComputerName SRV1,SRV2 | Export-Csv disks.csv -NoTypeInformation
- 过滤出可用率低于 15% 的盘:
.\Get-DiskInventory.ps1 -ComputerName SRV1 | Where-Object { $_.'%Free' -lt 15 }
八、最佳实践清单
-
输出对象而非文本;格式化交给调用者
-
参数都放在
param()
,并尽量:- 强制必须的参数(Mandatory)
- 明确类型
- 加别名(Alias)与验证(Validate*)
-
在脚本头写好基于注释的帮助(SYNOPSIS/DESCRIPTION/PARAMETER/EXAMPLE)
-
加上
[CmdletBinding()]
,无成本获得-Verbose/-ErrorAction
等 -
复杂表达式用
@{Name=;Expression= { … }}
计算属性 -
批量目标时返回带 ComputerName 字段的对象,便于后续筛选/聚合
九、课堂练习参考:Get-PhysicalAdapters.ps1
把第 12 章命令参数化、做成高级脚本,并加上 Verbose:
<#
.SYNOPSIS
获取物理网卡清单。
.DESCRIPTION
列出 Win32_NetworkAdapter 中 PhysicalAdapter 为 True 的适配器,输出对象便于导出。
.PARAMETER ComputerName
必填,计算机名或数组。别名 HostName。
.EXAMPLE
.\Get-PhysicalAdapters.ps1 -ComputerName SERVER01 -Verbose
#>
[CmdletBinding()]
param([Parameter(Mandatory=$true, HelpMessage='请输入要查询的计算机名')][Alias('HostName')][string[]] $ComputerName
)foreach ($comp in $ComputerName) {Write-Verbose "[$comp] 开始获取物理网卡"Get-WmiObject -Class Win32_NetworkAdapter -ComputerName $comp |Where-Object { $_.PhysicalAdapter } |Select-Object @{Name='ComputerName';Expression={$comp}},MACAddress, AdapterType, DeviceID, Name, SpeedWrite-Verbose "[$comp] 获取完成"
}
十、一页速查:把命令升级为“高级可传参脚本”的 8 步
- 把命令跑通,先写在 ISE/VS Code 里
- 改为对象输出(
Select-Object
计算属性) - 补上注释式帮助
- 顶部加
[CmdletBinding()]
- 用
param()
声明参数(类型、默认值) - 必要参数加
Mandatory
,易错参数加Validate*
,顺手加Alias
- 关键阶段写
Write-Verbose
- 用
-Verbose
、Export-Csv
、Format-Table
验收调用体验