- 文档
- 教程
【免费下载链接】learnxinyminutes-docs
Code documentation written as code! How novel and totally my idea!
PowerShell 是微软基于 .NET Framework 打造的脚本语言兼配置管理框架,Windows 7 及之后版本均内置,本指南完整覆盖从执行策略、帮助系统、变量与控制流,到 Provider、管道、函数、.NET 互操作与 Profile 配置的实战链路。读完本文,你将掌握用对象而非文本驱动 PowerShell 的核心思维,并能直接上手编写、调试和配置自己的 PowerShell 脚本。本文内容以 zh-cn/powershell.md 为骨架,结合仓库英文原版 powershell.md 与多语言版本(如 es/powershell.md)进行纵深补充。
一、PowerShell 是什么:对象优先的自动化框架
PowerShell 与 Bash 最大的不同在于:你大部分操作的是对象,而不是普通的文本。你在 Shell 中键入的每一条命令(cmdlet)返回的都是结构化对象,它们携带类型、属性与方法,可以进一步被管道下游命令消费。这正是 PowerShell 作为配置管理框架的基石——配置管理本质上就是"获取对象 → 筛选/变换对象 → 持久化/执行"的过程。
从仓库的英文原版 powershell.md 可以看出,PowerShell 官方将其定位为"跨平台任务自动化解决方案,由命令行 Shell、脚本语言和配置管理框架三部分组成",并在多年演进后呈现出与 Python 类似的风格。Windows PowerShell 5.1 随 Windows 系统分发、运行在 .NET Framework 之上;而 6+ 之后的开源版本(pwsh)则跨平台运行于 Windows、macOS 与 Linux。
以下示例中,几乎所有代码片段既可以作为.ps1脚本的一部分,也可以直接在 Shell 交互窗口中逐行执行。
二、运行环境检查:执行策略与版本信息
如果对你的环境不确定,先执行以下操作确认执行策略与版本:
# 列出当前生效的执行策略(含各作用域) Get-ExecutionPolicy -List Set-ExecutionPolicy AllSigned # Execution Policy 包含以下级别: # - Restricted: 不会运行脚本。 # - RemoteSigned: 只会运行受信任的发行商下载的脚本。 # - AllSigned: 运行需要被信任发行商签名的脚本。 # - Unrestricted: 运行所有脚本 help about_Execution_Policies # 查看更多信息 # 当前 PowerShell 版本 $PSVersionTable执行策略(Execution Policy)是 Windows 平台特有的安全防线,用于限制脚本的运行来源。英文原版 powershell.md 还补充了两个实用的环境探测手段:
# 查看当前运行的版本分支(Edition): # PowerShell 7+ 返回 "Core",Windows PowerShell 5.1 返回 "Desktop" $PSVersionTable.PSEdition这一区分非常重要:Desktop表明运行在 .NET Framework 之上,Core表明运行在跨平台的 .NET 之上,二者在可用 cmdlet 与兼容性上存在差异。
三、获取帮助:自文档化的命令体系
PowerShell 的命令、参数与模块都自带帮助文档,掌握查询方式可以大幅提升学习效率:
# 查找命令 Get-Command about_* # 别名: gcm Get-Command -Verb Add # 按动词过滤,如所有 Add-* 命令 Get-Alias ps # 查看 ps 的别名定义 Get-Alias -Definition Get-Process # 反向查询某个命令的所有别名 Get-Help ps | less # 别名: help,分页查看帮助 ps | Get-Member # 别名: gm,查看对象的方法与属性 Show-Command Get-EventLog # GUI 填充参数(交互式表单) # 英文原版使用 Show-Command Get-WinEvent,两者都是参数可视化填充的入口 Update-Help # 更新本地帮助库(Windows PowerShell 5.1 需管理员运行;7+ 不再要求)Get-Member是理解"对象思维"的第一把钥匙:把任意 cmdlet 的输出| gm,就能看到该对象上所有可用的属性与方法(参见 zh-cn/powershell.md 帮助章节)。例如Get-Date | gm会展示DateTime对象完整的成员清单。
四、语言基础:注释、Hello World 与变量
4.1 注释与基本输出
# 每一行开头是 # 的都是注释 # 简单的 Hello World 实例 echo Hello world! # echo 是 Write-Output (cmdlet) 的别名 # 大部分 cmdlet 和函数都遵循 "动词-名词" 命名规则。 # 每个命令都从新的一行开始,或者用分号分隔 echo 'This is the first line'; echo 'This is the second line'英文原版还展示了 PowerShell 特有的多行块注释语法(powershell.md):
<# Multi-line comments like so #>4.2 变量声明与赋值
PowerShell 变量名以$开头,没有严格的声明关键字,赋值即声明:
$aString="Some string" # 或者像这样: $aNumber = 5 -as [double] # 用 -as 做类型转换 $aList = 1,2,3,4,5 # 逗号分隔即数组 $anEmptyList = @() # 空数组 $aString = $aList -join '--' # 数组拼接为字符串,也包含 join 方法 $aHashtable = @{name1='val1'; name2='val2'} # 哈希表字面量4.3 字符串插值、转义与 Here-String
echo $aString echo "Interpolation: $aString" # 双引号内做变量插值 echo "$aString has length of $($aString.Length)" # $() 子表达式求值 echo '$aString' # 单引号内不做插值,' 不是变量的一部分 echo @" This is a Here-String $aString "@ # Here-String 同样支持单引号版本(此时不展开变量)英文原版补充了 PowerShell 的转义细节(powershell.md):多数语言用\转义,但 Windows 用\表示文件路径,因此 PowerShell 使用反引号`作为转义字符,且`本身是 NTFS 文件名中的合法字符,处理文件时需注意:
"Showing`nEscape Chars" # `n 表示换行 "Making`tTables`tWith`tTabs" # `t 表示制表符 `#Get-Process # 用反引号转义 #,阻止其被当作注释起始符4.4 内置(自动)变量
PowerShell 会话预置了一批自动变量,直接可用:
echo "Booleans: $TRUE and $FALSE" echo "Empty value: $NULL" echo "Last program's return value: $?" # 上一个命令的成功状态 echo "Exit code of last run Windows-based program: $LastExitCode" echo "The last token in the last line received by the session: $$" echo "The first token: $^" echo "Script's PID: $PID" echo "Full path of current script directory: $PSScriptRoot" echo 'Full path of current script: ' + $MyInvocation.MyCommand.Path echo "FUll path of current directory: $Pwd" # 注意:此处为目录对象 echo "Bound arguments in a function, script or code block: $PSBoundParameters" echo "Unbound arguments: $($Args -join ', ')." # 更多内置变量:help about_Automatic_Variables4.5 点操作符:内联执行其他脚本
# 内联其他文件(点操作符),在“当前作用域”执行其中的代码 . .\otherScriptName.ps1注意点操作符与&调用操作符的区别:.在当前作用域执行(对变量的修改会保留),而&在子作用域执行。英文原版对此有精确演示(powershell.md):
$i = 2 $scriptBlock = { $i=5; Write-Output $i } & $scriptBlock # => 5 $i # => 2 # & 调用后外部 i 未被修改 invoke-expression ' $i=5; Write-Output $i ' # => 5 $i # => 5 # Invoke-Expression 在当前作用域执行,i 被改写 $x=1 &{$x=2};$x # => 1 # 脚本块子作用域 .{$x=2};$x # => 2 # 点操作符保留修改4.6 调用外部可执行程序:调用操作符&
路径含空格的可执行程序直接输入会解析失败,必须使用调用操作符(powershell.md):
# 直接输入带空格的路径会报错:'C:\Program' 不是可识别的命令 C:\Program Files\dotnet\dotnet.exe # 必须用 & 显式调用 &"C:\Program Files\dotnet\dotnet.exe" --help # 成功 # 参数必须放在引号之外,否则整串会被当作单个命令 ."C:\Program Files\dotnet\dotnet.exe" --help # 点操作符同样可行4.7 数值、布尔与类型比较(英文原版补充)
英文原版系统梳理了基础运算语义(powershell.md),这里提炼几处易踩坑的关键点:
# 除法总是返回浮点数,取整需显式 [int] 转换 [int]$result = 5 / 3 $result # => 2 # 幂运算需要长格式或 .NET [Math] 类 [Math]::Pow(2,3) # => 8 # $True 与 $False 实质是 1 与 0,但算术支持有限 $True + $True # => 2 $True * 8 # => 报错:布尔与整数的乘法未定义 [int]$True * 8 # => 8 $False - 5 # => -5 # 比较运算符 -eq/-ne/-lt/-gt/-le/-ge 不区分大小写,c 前缀强制区分大小写 "ab" -eq "AB" # => True(默认不区分大小写) "ab" -ceq "AB" # => False "ab" -ieq "AB" # => True # $null、0、空字符串与空数组在布尔判断中为 False,其余为 True function Test-Value ($value) { if ($value) { Write-Output 'True' } else { Write-Output 'False' } } Test-Value ($null) # => False Test-Value (0) # => False Test-Value ("") # => False Test-Value @() # => False4.8 现代化运算符(PowerShell 7+)
英文原版补充了 PowerShell 7 系列引入的一批现代化语法(powershell.md):
# 三元运算符(PS 7+) 0 ? 'yes' : 'no' # => no # 空值合并 ?? 与空值合并赋值 ??=(PS 7+) $x = $null $x ?? 100 # => 100 $x ??= 100 # 仅在 $null 时赋值 $x ??= 200 $x # => 100(不再变化) # 空条件运算符 ?. 与 ?[](PS 7.1+):操作数为 $null 时安全返回 $null $a = $null ${a}?.PropName # => $null(不抛错) # 管道链式运算符 && 与 ||(PS 7+):基于左侧是否成功决定是否执行右侧 Write-Output 'Success' && Write-Output 'Also runs' # 两侧都输出 Write-Output 'Success' || Write-Output 'Skipped' # 只输出第一句 # 后台运算符 &(PS 6+):把管道作为后台作业执行,立即返回 Job 对象 Get-Process &五、控制流:条件、Switch、循环与异常
5.1 条件判断
if ($Age -is [string]) { echo 'But.. $Age cannot be a string!' } elseif ($Age -lt 12 -and $Age -gt 0) { echo 'Child (Less than 12. Greater than 0)' } else { echo 'Adult' }注意-is检查类型、-lt/-gt比较大小、-and/-or做逻辑组合——这些以-开头的比较与逻辑运算符是 PowerShell 语法的重要标志。
5.2 Switch 语句:比多数语言更强大
$val = "20" switch($val) { { $_ -eq 42 } { "The answer equals 42"; break } '20' { "Exactly 20"; break } { $_ -like 's*' } { "Case insensitive"; break } { $_ -clike 's*'} { "clike, ceq, cne for case sensitive"; break } { $_ -notmatch '^.*$'} { "Regex matching. cnotmatch, cnotlike, ..."; break } { 'x' -contains 'x'} { "FALSE! -contains is for lists!"; break } default { "Others" } }Switch 的分支可以是字符串字面量,也可以是任意脚本块表达式(配合$_做通配符匹配、正则匹配、类型判断等),这正是它"更强大"的体现。注意-contains用于列表成员判断,而不是字符串包含。
5.3 循环家族
# 经典的 For 循环 for($i = 1; $i -le 10; $i++) { "Loop number $i" } # 或者可以更简洁(1..10 是范围运算符,% 是 ForEach-Object 的别名) 1..10 | % { "Loop number $_" } # PowerShell 还提供其他循环方式 foreach ($var in 'val1','val2','val3') { echo $var } # while () {} # do {} while () # do {} until ()英文原版补充了while的典型写法与 foreach 配合格式化字符串-f的用法(powershell.md):
$x = 0 while ($x -lt 4) { Write-Output $x $x += 1 } foreach ($animal in ("dog", "cat", "mouse")) { "{0} is a mammal" -f $animal }5.4 异常处理
try {} catch {} finally {} try {} catch [System.NullReferenceException] { echo $_.Exception | Format-List -Force }catch可以按异常类型精确捕获;$_在 catch 块中指向当前错误对象,$_.Exception携带完整异常信息。英文原版示例还演示了throw主动抛错与finally清理资源(powershell.md)。
六、Provider:超越文件系统的导航模型
# 列出当前目录下的文件和子目录 ls # 或者 dir cd ~ # 回到主目录 Get-Alias ls # -> Get-ChildItem # 这些 cmdlet 有更加通用的名称,因为它不仅仅只操作当前目录,这一点和其他脚本语言不同。 cd HKCU: # 跳转 HKEY_CURRENT_USER 注册表中的值 # 获取当前会话中的提供者 Get-PSProviderProvider 是 PowerShell 的抽象文件系统模型:ls/cd不仅能导航文件系统,还能导航注册表(HKCU:、HKLM:)、环境变量、证书存储、变量空间等一切实现了 Provider 接口的存储。Get-PSProvider可以列出当前会话注册的所有提供者,这也是"配置管理框架"在命名空间层面的体现。
七、管道:对象流的筛选、变换与导出
7.1 参数控制与别名缩写
# Cmdlets 中的参数用来控制它们的行为: Get-ChildItem -Filter *.txt -Name # 获取所有 txt 文件名。 # 需要输入足够多的参数来确保没有歧义。 ls -fi *.txt -n # -f 是不可以的因为 -Force 同样存在。 # 使用 Get-Help Get-ChildItem -Full 来查看全部参数。参数支持"足够长以消除歧义"的前缀缩写,但缩写必须唯一——-f会与-Force冲突,而-fi明确指向-Filter。
7.2 管道连接与对象处理
# 之前 cmdlet 获取的结果输出可以作为下一个输入。 # $_ 指代当前管道处理的对象。 ls | Where-Object { $_.Name -match 'c' } | Export-CSV export.txt ls | ? { $_.Name -match 'c' } | ConvertTo-HTML | Out-File export.html # ? 是 Where-Object 的别名 # 如果对管道的对象感到疑惑,使用 Get-Member 来查看该对象的可使用的方法和属性。 ls | Get-Member Get-Date | gm7.3 行连续符与复杂管道
# ` 是行连续标识符,或者在每一行结尾添加一个 | Get-Process | Sort-Object ID -Descending | Select-Object -First 10 Name,ID,VM ` | Stop-Process -WhatIf # -WhatIf 做预演:只显示将要执行的操作而不真正执行 Get-EventLog Application -After (Get-Date).AddHours(-2) | Format-List # (Get-Date).AddHours(-2) 利用 .NET DateTime 方法构造时间参数7.4 ForEach-Object 的 Begin/Process/End 三段式
# 使用 % 作为 ForEach-Object 的简称。 ('a','b','c') | ForEach-Object ` -Begin { "Starting"; $counter = 0 } ` -Process { "Processing $_"; $counter++ } ` -End { "Finishing: $counter" }-Begin在管道开始前执行一次,-Process对每个输入对象执行,-End在所有处理结束后执行——适合做累加器、批处理首尾操作等场景。
7.5 计算属性与自定义表格列
# Get-Process 返回包含三列的表 # 第三列是使用 2 位精度数值表示 VM 属性 # 计算出来的列也可以表示更多的信息: # @{name='lbl';expression={$_} ps | Format-Table ID,Name,@{n='VM(MB)';e={'{0:n2}' -f ($_.VM / 1MB)}} -autoSize计算属性的语法为@{name='列名';expression={脚本块}}(可简写为n/e),这里把 VM 字节数除以 1MB 并格式化为两位小数,输出一张可读性极佳的内存占用表。
7.6 管道进阶:分组、并行与作业(英文原版补充)
英文原版系统补充了管道的进阶玩法(powershell.md):
# Group-Object 类似 SQL 的 GROUP BY:按进程名分组并统计实例数 Get-Process | Foreach-Object ProcessName | Group-Object # 范围 + 过滤 + JSON 导出 1..10 | ForEach-Object { "Loop number $PSITEM" } 1..10 | Where-Object { $PSITEM -gt 5 } | ConvertTo-Json # ForEach-Object -Parallel(PS 7+):并行执行脚本块 $logNames = 'Security','Application','System','Windows PowerShell' $logEntries = $logNames | ForEach-Object -Parallel { Get-WinEvent -LogName $_ -MaxEvents 1000 } -ThrottleLimit 4 # 最大 4 个并发线程(默认 5) # 使用 $using: 作用域修饰符把外部变量传入并行块 $maxEvents = 500 1..5 | ForEach-Object -Parallel { "Processing item $_ with max $using:maxEvents" } # 作业(Job):把慢速命令放入后台执行,主线程不阻塞 $scriptBlock = {Get-CimInstance -ClassName Win32_Product} Start-Job -ScriptBlock $scriptBlock $allJobs = Get-Job $jobResponse = Get-Job | Receive-Job英文原版还提醒了管道的两个已知坑(powershell.md):一是管道相比其他方案存在性能开销,二是原始字节不经过管道,因此传递图片等二进制数据会出问题。
八、函数:从简单定义到高级函数
8.1 简单函数
# [string] 注记是可选的。 function foo([string]$name) { echo "Hey $name, have a function" } # 调用你的函数 foo "Say my name"注意 PowerShell 函数调用不使用括号传参,直接空格分隔即可。
8.2 高级函数:参数特性与可解析文档
# 函数可以包含命名参数、参数的注记和可解析的文档 <# .SYNOPSIS Setup a new website .DESCRIPTION Creates everything your new website needs for much win .PARAMETER siteName The name for the new website .EXAMPLE New-Website -Name FancySite -Po 5000 New-Website SiteWithDefaultPort New-Website siteName 2000 # ERROR! Port argument could not be validated ('name1','name2') | New-Website -Verbose #> function New-Website() { [CmdletBinding()] param ( [Parameter(ValueFromPipeline=$true, Mandatory=$true)] [Alias('name')] [string]$siteName, [ValidateSet(3000,5000,8000)] [int]$port = 3000 ) BEGIN { Write-Verbose 'Creating new website(s)' } PROCESS { echo "name: $siteName, port: $port" } END { Write-Verbose 'Website(s) created' } }这段示例浓缩了高级函数(Advanced Function)的多个核心机制:
[CmdletBinding()]:把普通函数升级为与 cmdlet 同等能力的"高级函数",获得-Verbose、-WhatIf等公共参数;[Parameter(...)]:声明参数行为,ValueFromPipeline=$true表示可从管道按值接收输入,Mandatory=$true表示必填;[Alias('name')]:为参数定义别名;[ValidateSet(3000,5000,8000)]:参数取值校验集合,传2000会触发 "Port argument could not be validated" 错误;BEGIN/PROCESS/END块:与 ForEach-Object 的三段式一致,配合管道逐对象处理输入。
8.3 函数进阶补充(英文原版)
英文原版补充了param块的独立写法与Clean块(powershell.md):
# 用 param() 声明参数并做类型强制 function Add-ParamNumbers { param( [int]$firstNumber, [int]$secondNumber ) $firstNumber + $secondNumber } Add-ParamNumbers -FirstNumber 1 -SecondNumber 2 # => 3 # Clean 块(PS 7.3+):无论是否发生错误都会执行,适合释放非托管资源 function Get-Data { [CmdletBinding()] param() begin { $resource = Open-Something } process { $resource | Do-Something } end { } clean { if ($resource) { $resource.Dispose() } } }九、都是 .NET:类型系统的完全开放
9.1 字符串就是 System.String
# PS 中的字符串事实上就是 .NET 的 System.String 类型 # 所有 .NET 方法和属性都可用 'string'.ToUpper().Replace('G', 'ggg') # 或者更加 PowerShell 一点 'string'.ToUpper() -replace 'G', 'ggg' # 不确定这样的话 .NET 方法如何调用 'string' | gm9.2 静态方法调用与 COM/IO 对象
# 调用静态 .NET 方法的语法:[Namespace.Class]::StaticMethod(args) [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') # 注意 .NET 方法调用必须使用括号,然而 PS 函数调用不能使用括号; # 如果你调用 cmdlet/PS 函数使用了括号,就相当于传递了参数列表。 $writer = New-Object System.IO.StreamWriter($path, $true) $writer.Write([Environment]::NewLine) $writer.Dispose()英文原版补充了静态成员的可发现性(powershell.md):
# 数学计算直接用 .NET Math 类 $r = 2 $pi = [math]::pi $area = $pi * [math]::pow($r, 2) $area # 查看 Math 类的全部静态成员 [System.Math] | Get-Member -Static -MemberType All9.3 类型化集合:数组、ArrayList、泛型 List 与哈希表
英文原版用专门篇幅讲透了集合语义(powershell.md),这是中文版未展开但实战中极易踩坑的部分:
# PowerShell 默认数组是固定长度数组,+= 只能"新增"不能删除 $defaultArray = "thing","thing2","thing3" $defaultArray.Add("thing4") # => 异常:集合大小固定 # 可动态增删用 .NET ArrayList(现代更推荐泛型 List) [System.Collections.ArrayList]$array = @() $array.Add(1) > $null # Add 会产生输出,重定向到 $null 抑制 $array.RemoveAt($array.Count-1) # 按下标删除末尾元素 $array.Insert(2, 3) # 在指定下标插入 $array.IndexOf(2) # 查找元素下标,找不到返回 -1 $array + $otherArray # 数组相加生成新数组 $array.AddRange($otherArray) # 原地拼接 # 泛型 List(现代推荐,类型安全) [System.Collections.Generic.List[int]]$typedList = @() $typedList.Add(42) $typedList.Add(99) # 切片语法与 -eq 对数组的"过滤"语义 $array[1,3,5] # 选取指定下标 => [2, 4, 6] $array[1..3] # 下标 1 到 3 => [2, 3, 4] $array[-3..-1] # 末尾 3 个 => [6, 7, 8] $array = 1,2,3,1,1 $array -eq 1 # => 1,1,1(-eq 对数组不是整体比较,而是取出匹配元素) ($array -eq 1).Count # => 3 # 哈希表 $filledHash = @{"one"= 1; "two"= 2; "three"= 3} $filledHash["one"] # => 1 $filledHash.Keys # 所有键 $filledHash.Add("five",5) # 键已存在会抛异常 $filledHash["four"] = 4 # 下标赋值,重复执行不会报错 $filledHash.Remove("one") "one" -in $filledHash.Keys # => True(-in 做成员判断)英文原版还提示:PowerShell 7.5 中对对象数组的+=操作做了显著优化,性能较旧版本大幅提升(powershell.md),但在高频场景仍建议优先使用泛型 List。
十、IO 与文件处理
10.1 控制台输入
# 从输入读入一个值 $Name = Read-Host "What's your name?" echo "Hello, $Name!" [int]$Age = Read-Host "What's your age?"Read-Host返回字符串,可以用类型前缀[int]直接转换读取结果。
10.2 路径与内容处理
# Test-Path, Split-Path, Join-Path, Resolve-Path 是路径处理四件套 # Get-Content filename # 返回字符串数组 string[] # Set-Content, Add-Content, Clear-Content # 写、追加、清空 Get-Command ConvertTo-*,ConvertFrom-* # 查看全部转换类命令Get-Command ConvertTo-*,ConvertFrom-*会列出ConvertTo-CSV、ConvertTo-HTML、ConvertTo-Json、ConvertFrom-Json、ConvertFrom-CliXml等全部格式转换命令,是数据导出与序列化的命令总览。英文原版补充了 CSV 导出与 JSON 互转的实战片段(powershell.md):
$contents = @{"aa"= 12; "bb"= 21} $contents | Export-CSV "$env:HOMEDRIVE\file.csv" # 对象导出为 CSV Get-Content "$env:HOMEDRIVE\file.csv" | ConvertTo-Json # 读取并转 JSON十一、有用的实战技巧
# 更新 PATH $env:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") # 找到 Python 的 PATH $env:PATH.Split(";") | Where-Object { $_ -like "*python*"} # 改变工作目录而不需要记住之前的路径 Push-Location c:\temp # 改变工作目录至 c:\temp Pop-Location # 改变到之前的工作目录 # 别名: pushd 和 popd # 在下载之后解除目录阻塞(解除 Mark-of-the-Web) Get-ChildItem -Recurse | Unblock-File # Windows 资源管理器打开当前目录 ii . # 按任意键退出 $host.UI.RawUI.ReadKey() return # 创建快捷方式 $WshShell = New-Object -comObject WScript.Shell $Shortcut = $WshShell.CreateShortcut($link) $Shortcut.TargetPath = $file $Shortcut.WorkingDirectory = Split-Path $file $Shortcut.Save()其中几个片段值得展开说明:
$env:PATH直接读写"环境变量驱动器"(env:Provider),把 Machine 级与 User 级的 Path 合并;Push-Location/Pop-Location维护目录栈,pushd/popd是它们在cmd时代的别名;Unblock-File针对从互联网下载的文件解除 Zone.Identifier 阻塞,避免后续运行被拦截;New-Object -comObject WScript.Shell演示了通过 COM 互操作调用 WScript 创建快捷方式。
十二、远程与多服务器自动化(英文原版补充)
英文原版在"PowerShell as a Tool"部分补充了远程管理能力(powershell.md),这是中文版"尚未涉及"清单中明确提到的方向,此处补齐:
# 进入远程会话(Windows 传统方式) Enter-PSSession -ComputerName RemoteComputer # PowerShell 6+ 支持通过 SSH 跨平台远程 Enter-PSSession -HostName user@ssh.example.com:22 # 进入远程后如同本地一样执行命令 RemoteComputer\PS> Get-Process powershell RemoteComputer\PS> Exit-PSSession # 批量场景:对 10 台服务器并行下发作业,检查服务状态 $serverList = @('server1','server2', ... ,'server10') [scriptblock]$script = { Get-Service -DisplayName 'Task Scheduler' } foreach ($server in $serverList) { $cmdSplat = @{ ComputerName = $server JobName = 'checkService' ScriptBlock = $script AsJob = $true # 异步作业方式执行 ErrorAction = 'SilentlyContinue' } Invoke-Command @cmdSplat | Out-Null } # 之后用 Get-Job / Receive-Job 收集各服务器结果这里还展示了**参数展开(Splatting)**技巧:把参数放进哈希表,用@cmdSplat(注意是@而非$)展开传给Invoke-Command。直接传$cmdSplat会把整个哈希表当作单个对象传递,行为完全不同。
十三、配置你的 PowerShell:Profile 与模块生态
13.1 Profile:每次会话启动自动加载
# $Profile 是文件 Microsoft.PowerShell_profile.ps1 的完整路径 # 下面所有的代码都在 PS 会话开始的时候执行 if (-not (Test-Path $Profile)) { New-Item -Type file -Path $Profile -Force notepad $Profile } # 更多信息: help about_profiles$Profile指向当前用户、当前宿主(console/ISE/VS Code)对应的 Profile 脚本。首次使用先创建文件,之后把别名、函数、$env:PATH修改等"每次都要执行"的代码写进去,即可实现个性化环境。更多信息参考help about_profiles,命令行编辑体验可以进一步了解 PSReadLine 项目(Windows 10 及 PowerShell 7 默认内置)。
13.2 模块:安装、导入与调用(英文原版补充)
英文原版补充了模块管理(powershell.md),对应中文版列举的 PSGet 项目(PowerShell 的 NuGet 包管理器):
# 安装模块:类似 pip / npm,从 PowerShell Gallery 拉取 Install-Module dbaTools # 传统方式(PowerShellGet) Install-PSResource dbaTools # 现代方式(PSResourceGet,PS 7.4+) # 导入模块后即可调用其中的命令 Import-Module dbaTools $query = "SELECT * FROM dbo.sometable" $queryParams = @{ SqlInstance = 'testInstance' Database = 'testDatabase' Query = $query } Invoke-DbaQuery @queryParams # 用 @ 展开哈希表为命名参数 # 只导入模块中的特定函数 Import-Module -Function Invoke-DbaQuery # 查看模块提供的命令与帮助 Get-Command -module dbaTools Get-Help dbaTools -Full13.3 类与枚举(英文原版补充)
英文原版还涵盖了 PowerShell 5+ 的面向对象能力(powershell.md),可视为配置管理框架中"自定义对象模型"的延伸:
# class 定义 class Instrument { [string]$Type [string]$Family } $instrument = [Instrument]::new() $instrument.Type = "String Instrument" $instrument.Family = "Plucked String" # 继承 class Guitar : Instrument { [string]$Brand [string]$SubType } $myGuitar = [Guitar]::new() $myGuitar.GetType() # BaseType 显示为 Instrument # 枚举:类型安全、限定输入集合 enum Color { Red; Green; Blue } [Color]::Red # => Red [Color]'Green' # => Green # Flags 枚举:位组合 [Flags()] enum FilePermission { Read = 1 Write = 2 Execute = 4 } [FilePermission]::Read -bor [FilePermission]::Write # => Read, Write十四、新版本特性速览(PowerShell 6.x+,英文原版补充)
英文原版以独立章节列出 PowerShell 6.x 以来的新 cmdlet 与特性(powershell.md),可作为升级到pwsh后的快速参考:
# Get-Error:结构化错误查看(PS 7.0+),$ErrorView 默认 ConciseView $Error | Get-Error Get-Error -Newest 3 # Get-Uptime:距上次启动的时间(PS 6+) Get-Uptime # Join-String:把管道对象拼接成字符串(PS 6.2+) "one","two","three" | Join-String -Separator ", " # => one, two, three # Test-Json:校验 JSON 字符串(PS 6.1+) '{"name": "test"}' | Test-Json # => True # PS 7.5+ 支持 -IgnoreComments 与 -AllowTrailingCommas '{"name": "test", /* comment */ }' | Test-Json -AllowTrailingCommas -IgnoreComments # ConvertTo-CliXml / ConvertFrom-CliXml(PS 7.5+):不落盘的对象序列化 $obj = [pscustomobject]@{ Name = "test"; Value = 42 } $obj | ConvertTo-CliXml | ConvertFrom-CliXml # ConvertFrom-Json -DateKind(PS 7.5+):控制 JSON 日期解析 '{"dt": "2024-01-15T10:30:00Z"}' | ConvertFrom-Json -DateKind Utc # Where-Object -Not(PS 6+):按"无依赖服务"过滤 Get-Service | Where-Object -Not DependentServices # Markdown 处理 cmdlet(PS 6.1+) "**bold** and *italic*" | ConvertFrom-Markdown | Show-Markdown # Remove-Alias(PS 6+)、Remove-Service(PS 6+) Remove-Alias -Name myAlias # Get-Process -IncludeUserName 不再需要管理员权限(PS 7.5+) Get-Process -IncludeUserName十五、延伸学习与尚未涉及的主题
仓库文档末尾还给出了延伸资源与"尚未涉及"清单。延伸资源(详见 zh-cn/powershell.md 与英文原版 powershell.md 的 "Interesting Projects")包括:Channel9 管道专题教程、PSGet(PowerShell 的 NuGet 包管理器)、PSReadLine(仿 Bash 的按行读取,Windows 10 默认包含)、Posh-Git(Git 命令提示)、PSake(自动构建工具)、Pester(BDD 测试框架)、Jump-Location / ZLocation(智能目录跳转)以及 PowerShell Community Extensions(PS Cmdlet 扩展集合)。
原文档明确列出以下尚未涉及的主题,作为你继续深入的方向:
- WMI:Windows 管理规范(
Get-CimInstance); - 多任务:
Start-Job -scriptBlock {...}(详见本文"管道进阶"中的作业示例); - 代码签名:与执行策略的 AllSigned/RemoteSigned 配合,用 Authenticode 签名脚本;
- 远程管理:
Enter-PSSession/Exit-PSSession、Invoke-Command(详见本文第十二节)。
这些主题连同 powershell.md 中"类与枚举、模块管理、并行管道、远程批量作业、新版本特性"等内容,构成了从入门到自动化运维的完整学习路线。
结语:从脚本到配置管理框架
回顾整条学习路径:执行策略与帮助系统解决"环境与可发现性"问题;变量、控制流、函数解决"语言表达"问题;Provider 与管道解决"对象导航与变换"问题;.NET 互操作把整个 .NET 类库变成你的工具箱;Profile 与模块生态解决"环境个性化与复用"问题;远程会话与作业则把单机脚本扩展为多服务器配置管理。正如英文原版开篇所言,PowerShell 的核心理念是操作对象而非文本——理解并善用这一理念,你就能从"写命令"进阶到"编排自动化"。
- 文档
- 教程
【免费下载链接】learnxinyminutes-docs
Code documentation written as code! How novel and totally my idea!
相关推荐
Learn X in Y Minutes 系列精读:Bash 脚本语言速成实战指南
Learn X in Y Minutes 系列精读:Bash 脚本语言速成实战指南 导读 本文基于本仓库的 fr/bash.md https://link.gi
文档教程Learn X in Y minutes:JavaScript 语言核心语法与 ES6+ 实战指南(fr 版全解)
Learn X in Y minutes:JavaScript 语言核心语法与 ES6+ 实战指南(fr 版全解) 本指南以仓库中 fr/javascript.
文档教程Learn X in Y minutes:Perl 语言快速入门与实战指南
Learn X in Y minutes:Perl 语言快速入门与实战指南 导读 本文以开源仓库 learnxinyminutes docs 中的 bg/per
文档教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考