PowerShell 实战的重点不是把语法背全,而是把一次性命令整理成可复用、可调试、可审计的自动化单元。函数、模块、错误处理和调试能力,决定脚本能不能从“自己机器上能跑”进入长期维护。
函数
函数定义和调用
使用 function 关键字定义可复用的代码块:
function Get-Greeting {
Write-Output "Hello, World!"
}
Get-Greeting函数参数
通过 param 块定义参数,支持默认值和类型约束:
function Get-Greeting {
param (
[string]$name = "World"
)
Write-Output "Hello, $name!"
}
Get-Greeting -name "Alice"返回值
函数通过 return 或管道输出返回值:
function Add-Numbers {
param ([int]$a, [int]$b)
return $a + $b
}
$result = Add-Numbers -a 5 -b 3高级函数
使用 [CmdletBinding()] 和 ValueFromPipeline 支持管道输入:
function Get-Square {
[CmdletBinding()]
param (
[Parameter(Mandatory, ValueFromPipeline)]
[int]$number
)
process {
return $number * $number
}
}
1..5 | Get-Square模块
模块概念
模块是将相关函数、变量和资源组织在一起的打包方式,便于重用和分发。模块文件以 .psm1 为扩展名。只要脚本开始被多个项目或多台机器复用,就应该考虑模块化。
创建和使用模块
- 创建
MyModule.psm1文件:
function Get-Greeting {
param ([string]$name = "World")
Write-Output "Hello, $name!"
}
Export-ModuleMember -Function Get-Greeting- 导入并使用:
# 确保模块路径在 $env:PSModulePath 中
Import-Module -Name "MyModule"
Get-Greeting -name "Alice"Import-Module 和 Export-ModuleMember
Import-Module:加载模块使命令可用。Export-ModuleMember:在.psm1中指定哪些函数对外暴露。
错误处理
try/catch/finally
try {
$result = Get-Process -Name "Notepad"
Write-Output "Process found: $($result.Name)"
} catch {
Write-Output "An error occurred: $_"
} finally {
Write-Output "Cleanup complete."
}按异常类型捕获
try {
$result = Get-Process -Name "Notepad"
} catch [System.Management.Automation.CommandNotFoundException] {
Write-Output "Command not found: $_"
} catch [System.Exception] {
Write-Output "General error: $_"
}自定义错误处理
结合 -ErrorAction Stop 在函数中处理错误:
function Get-ProcessInfo {
param ([string]$processName)
try {
$process = Get-Process -Name $processName -ErrorAction Stop
Write-Output "CPU: $($process.CPU)"
} catch {
Write-Output "Process '$processName' not found."
}
}调试
断点调试
# 设置断点
Set-PSBreakpoint -Script "C:\Path\To\Script.ps1" -Line 5
# 查看断点
Get-PSBreakpoint
# 移除断点
Remove-PSBreakpoint -Id 0调试命令
Get-PSBreakpoint:查看当前断点Enable-PSBreakpoint/Disable-PSBreakpoint:启用/禁用断点Get-PSCallStack:查看调用堆栈
Write-Debug 和 Write-Verbose
配合 [CmdletBinding()] 使用 -Debug 和 -Verbose 开关:
function Test-Logging {
[CmdletBinding()]
param ([string]$message)
Write-Debug "Debug: $message"
Write-Verbose "Verbose: $message"
}
Test-Logging -message "Test" -Debug -Verbose文件系统管理
基本操作
# 创建
New-Item -Path "C:\Example" -ItemType Directory
New-Item -Path "C:\Example\file.txt" -ItemType File
# 查看
Get-ChildItem -Path "C:\Example"
Get-ChildItem -Path "C:\Example" -Recurse # 递归
Get-ChildItem -Path "C:\Example\*.txt" # 通配符
# 读取和写入
Get-Content -Path "C:\Example\file.txt"
Set-Content -Path "C:\Example\file.txt" -Value "Hello"
Add-Content -Path "C:\Example\file.txt" -Value "Appended line"
# 复制、移动、删除
Copy-Item -Path "file.txt" -Destination "copy.txt"
Move-Item -Path "file.txt" -Destination "moved.txt"
Remove-Item -Path "C:\Example" -Recurse压缩和解压
Compress-Archive -Path "C:\Example" -DestinationPath "archive.zip"
Expand-Archive -Path "archive.zip" -DestinationPath "C:\Unzipped"进程与服务管理
进程管理
# 查看进程
Get-Process
Get-Process -Name "notepad"
# 启动和停止
Start-Process -FilePath "notepad.exe"
Stop-Process -Name "notepad"
# 详细信息
Get-Process -Name "notepad" | Select-Object Name, Id, CPU, WS服务管理
# 查看服务
Get-Service
Get-Service -Name "wuauserv"
# 启动、停止、重启
Start-Service -Name "wuauserv"
Stop-Service -Name "wuauserv"
Restart-Service -Name "wuauserv"
# 设置启动类型
Set-Service -Name "wuauserv" -StartupType Automatic自动化任务
计划任务
# 创建计划任务(每天 8:00 执行脚本)
$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument '-NoProfile -File C:\Scripts\Backup.ps1'
$trigger = New-ScheduledTaskTrigger -Daily -At 8am
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -TaskName "DailyBackup"
# 查看
Get-ScheduledTask -TaskName "DailyBackup"
# 修改触发器
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday,Wednesday,Friday -At 8am
Set-ScheduledTask -TaskName "DailyBackup" -Trigger $trigger
# 删除
Unregister-ScheduledTask -TaskName "DailyBackup" -Confirm:$false自动化脚本示例
自动清理超过 30 天的日志文件:
$logPath = "C:\Logs"
$daysOld = 30
Get-ChildItem -Path $logPath -Filter *.log |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$daysOld) } |
Remove-Item -Force
Write-Output "Old log files cleaned up."使用原则
函数要像 cmdlet 一样可组合:参数明确、输出对象稳定、错误可捕获,才能放进管道和自动化流程。
模块化是复用边界:多个脚本共享的函数不要复制粘贴,放进模块并明确导出内容。
错误处理要区分终止和非终止错误:需要进入 catch 的命令常常要配合 -ErrorAction Stop。
系统管理脚本默认有风险:删除文件、停止服务、注册计划任务前,优先提供 -WhatIf、日志和确认边界。
计划任务要可观察:自动运行的脚本必须有日志、退出码和失败通知,否则就是静默风险。