☰
PowerShell高效进阶:从常用命令到自动化脚本的实战指南
2026/9/30 1:35:28 网站建设 项目流程

PowerShell这个东西,Windows用户早晚都得碰一下。不管是排查“C盘怎么又满了”、启动一个Elasticsearch服务、批量给一堆电脑装环境,还是单纯想把每天重复的复制粘贴工作省掉几遍,PowerShell都是最顺手的那个入口。它不像老CMD那样只能跟纯文本打交道,也不像Linux里的Bash那样在Windows上总有点水土不服——它是一整套基于对象的自动化平台,自带一套叫“命令大全”都嫌小的命令体系。我写这篇博文,就是想把这些年真正高频用到的PowerShell命令、脚本习惯、报错场景都梳理一遍,争取让读者从“复制别人代码”慢慢进阶到“自己会查、会猜、会写”。

有基础的朋友可以直接跳到后面看实战案例,纯新手的建议从头顺着读,每一步我都尽量带上“为什么这么做”的解释,而不是丢一堆参数让你硬背。

1. 先搞清楚PowerShell到底是什么,为什么值得背它的命令

1.1 从CMD到PowerShell:一个更彻底的命令行世界

很多Windows用户对PowerShell的第一印象就是“换了个名字的CMD”,这种理解不能算全错,但会严重低估它的价值。CMD做的事情是把操作系统的能力通过文本命令暴露出来,输出结果是一堆字符串;而PowerShell的核心思路是把一切操作对象化——文件是对象、进程是对象、服务也是对象。打个比方,CMD的管道传的是“纸条”,传过去之后你还得重新读一遍才知道上面写了什么;PowerShell的管道传的是“带标签的箱子”,每一项数据都有明确的类型和字段,后面的命令打开箱子就能直接用。

基于这个设计,微软给PowerShell命令定了一套非常容易猜的命名规范:动词-名词。Get表示读取,Set表示修改,New表示创建,Remove表示删除,Start和Stop表示启动和停止。你想看进程列表,不用记奇怪缩写,写Get-Process就行;想停止某个进程,把Get换成Stop,就是Stop-Process。这套规则对不喜欢死记硬背的人非常友好,遇到不认识的命令,可以用Get-Command按“动词+名词”的规律去猜,猜完再用Get-Help验证一下,基本八九不离十。

1.2 什么人最需要这份命令清单

PowerShell适合三类人。第一类是开发者和运维,日常要在本地启动Elasticsearch、Redis、Docker这类服务,或者连上服务器做日志检索、端口排查、服务启停,PowerShell就是最顺手的操作台。第二类是系统管理员,要做批量部署、开机自启、安全日志审计、计划任务,脚本化之后效率翻倍。第三类是普通Windows用户,系统卡了想看哪个进程占内存,C盘满了想找出大文件,弹窗广告想删掉开机启动项,这些都可以在PowerShell里用几行命令搞定。

另外多说一句,现在很多运行在Windows上的第三方工具,装完后你仍然要在命令行里敲它们——Git、Docker、Node、Python、conda、vim,全都一样。PowerShell作为宿主,几乎是Windows下所有命令行工具的“通用入口”。哪怕你只写前端,只做数据分析,也躲不开要跟这个黑窗口打交道。

2. 打开PowerShell与版本选择:别在入口就卡住

2.1 快速打开PowerShell的多种姿势

经常有人问我“PowerShell怎么打开”,这问题听起来很简单,但确实有人在入口就卡住。我平时最常用的几种方式,按效率排个序:

  1. 按Win+X,在弹出的菜单里选“Windows PowerShell”或“终端”。
  2. 按Win+R,输入powershell,回车。
  3. 在资源管理器地址栏直接输入powershell,回车——这个方式有个隐藏优势,打开后当前目录就是你正在看的文件夹,省得再费力切路径。
  4. 开始菜单直接搜“powershell”或“pwsh”。

这里有个细节特别强调一下:如果接下来要操作磁盘、服务、系统文件,建议右键选择“以管理员身份运行”。我见过很多次“访问被拒绝”的报错,根本不是命令写错,而是普通权限窗口没资格动系统级资源。判断方法很简单,看窗口标题,标题里有“管理员”三个字,说明是提权状态。原理上,PowerShell继承当前进程的用户访问令牌,普通权限的令牌即便在命令里加-Force也没有用,操作系统访问控制层会直接拒绝。

2.2 版本怎么选:5.1还是7.x

Windows里至少有“两个长得不一样”的PowerShell。系统自带的是Windows PowerShell 5.1,它基于.NET Framework,和Windows系统组件深度绑定,老脚本兼容性最好;另一个是PowerShell 7.x,基于.NET,支持跨平台,启动更快、字符处理更现代,但和系统组件的耦合度低。两个版本完全可以共存,平时执行老脚本用5.1,自己写新东西我用7.x。在命令行里输入powershell打开的是5.1,输入pwsh打开的才是7.x,别搞混。

先看自己现在是什么版本,直接在PowerShell里执行$PSVersionTable,返回结果里有个PSVersion字段,就是当前版本号。升级PowerShell 7最简单的方式是winget install Microsoft.PowerShell;对5.1,一般不用主动升级,系统更新会带着补丁一起打。如果因为特殊原因必须装5.1,Win7这类老系统对补丁依赖比较强,装之前最好把.NET Framework和系统更新补齐,安装包从微软官方渠道下载,不要信第三方“一键安装”。

2.3 执行策略:第一个“无法加载”警告的真相

新用户第一次运行.ps1脚本,经常会看到一个红字提示:无法加载文件,因为在此系统上禁止运行脚本。这不是脚本坏了,是执行策略在保护你。默认情况下,Windows PowerShell的ExecutionPolicy是Restricted,不允许本机运行任何脚本。微软设计这套机制,是为了防止恶意脚本在用户不知情的情况下被双击执行。

常见策略有Restricted、AllSigned、RemoteSigned、Unrestricted、Bypass几档。对个人开发机,我推荐RemoteSigned:本地自己写的脚本可以运行,从网络下载的脚本要求有数字签名。设置命令是Set-ExecutionPolicy RemoteSigned,需要管理员权限。

还有一种临时放行方式:powershell -ExecutionPolicy Bypass -File xxx.ps1,只对当次命令生效,不改变系统设置。这种用法比较克制,适合你明确知道脚本内容可信、但不想全局放开策略的场景。反过来也要提醒一句:平时看到“从网络下载脚本然后直接执行”的做法要谨慎,脚本在你机器上拥有和你一样的权限,别人写好的脚本,先看清楚再跑。

3. 高频命令实战:文件、进程、网络与服务

3.1 文件和目录操作:先学会用管道筛选

文件目录操作是最高频的场景,先掌握几个最基本的。切换目录用Set-Location,也可以直接用别名cd;查看当前位置用Get-Location,别名pwd;列出内容用Get-ChildItem,别名ls或dir。CMD习惯的玩家到这里都不会陌生。关键在参数:-Recurse表示递归子目录,-Filter用来做过滤,-ErrorAction SilentlyContinue让命令遇到没权限的目录时不要刷屏报错、直接跳过。

一个非常实用的场景:找出C盘里大于1GB的文件。一条命令就能搞定:

Get-ChildItem -Path C:\ -Recurse -File -ErrorAction SilentlyContinue | Where-Object Length -gt 1GB | Sort-Object Length -Descending | Select-Object FullName, @{Name='大小GB'; Expression={[math]::Round($_.Length/1GB,2)}}

这段就是“先列所有文件,再筛选大于1GB的,按大小倒序排,最后只输出路径和换算后的大小”。如果不想看C盘全盘,可以把-Path C:\改成具体目录,速度会快很多。

复制、移动、删除的命令分别是Copy-Item、Move-Item、Remove-Item,配合-Recurse和-Force使用。Remove-Item的-Force参数很危险,删文件时它会绕过只读属性,删目录时报错也少,稍不注意就会把不该删的东西删掉。所以行动前务必确认路径正确,必要的时候先在末尾加上-WhatIf参数预演一遍,看看命令到底会动哪些文件。

3.2 进程与服务排查:系统卡顿自救指南

系统卡顿的时候,PowerShell是很好的体检工具。先看谁在吃CPU:

Get-Process | Sort-Object CPU -Descending | Select-Object -First 10

输出的前几行基本就是罪魁祸首。确认某个进程要结束后,用Stop-Process -Name notepad -Force这样的命令直接终止。这里提醒一下,-Force对Stop-Process来说是“强制结束”,有些程序来不及保存数据,所以我一般先不用-Force,杀不掉再加。

服务排查比进程更常用。Get-Service可以列出所有服务,想看哪些在运行:

Get-Service | Where-Object Status -eq 'Running'

重启打印机服务、重启IIS服务这类操作,一条Restart-Service -Name spooler就完成了。比较麻烦的是“进程已经看到了,但不知道它属于哪个服务”的情况,这时候用Win32_Service类查询:

Get-CimInstance Win32_Service | Where-Object ProcessId -eq 12345

把12345换成进程ID,就能反查进程ID对应的服务名、显示名、启动类型。排查服务器异常时这一招非常管用。

如果想看安全日志里有没有大量失败的登录尝试,可以用:

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 20

输出里能看到最近20条登录失败记录,包括来源IP和用户名。系统管理员审计账户安全时,这条命令比在事件查看器里点来点去快得多。

3.3 网络诊断:一条命令替代telnet测端口

早年间排查网络,最常用的命令是telnet ip 端口,用来测试某台机器的某个端口通不通。但Windows 10/11默认不装telnet客户端,装起来还麻烦,而且telnet一旦连上就是黑屏等待,用户体验很差。我后来基本只用一条命令替代:

Test-NetConnection -ComputerName 192.168.1.10 -Port 3389

返回结果里看TcpTestSucceeded字段,True代表端口通,False代表不通。这个命令本质上是把“ping测试+DNS解析+TCP端口测试+路由追踪”都做了一遍,加个-TraceRoute参数还能顺便看经过的路由节点。

查本机端口占用也是高频场景。比如启动服务时提示8080端口被占用,先看谁在监听:

Get-NetTCPConnection -State Listen Get-NetTCPConnection -LocalPort 8080

拿到OwningProcess字段的PID后,再用Get-Process -Id 8080的PID去确认是哪个程序。这一套组合拳查端口冲突特别顺手。

再配合日常服务排查说一下:在Windows上启动Elasticsearch,启动完通常要确认9200端口是否起来了,直接Test-NetConnection -ComputerName localhost -Port 9200,返回True就说明服务就绪。Redis默认6379,Docker映射的端口也可以这样验证。网络命令不用背太多,把Test-NetConnection、Get-NetTCPConnection、Resolve-DnsName这三个用熟,大部分问题都能解决。

3.4 在PowerShell里调用外部命令:git、docker、服务启动都是它的活儿

单论文件、进程、网络,这些都是PowerShell自家的命令,但实际工作里更常出现的是“在PowerShell里敲别人家的程序”。Git、Docker、Node、conda、vim,装好之后都会被加进PATH,直接敲名字就能跑:git status、docker ps、python --version,PowerShell不会拦你。

有几个小坑值得记一下。第一,如果程序路径里有空格,直接敲路径会报“不是内部或外部命令”,这时候用调用操作符&:& 'C:\Program Files\MyTool\tool.exe' -param。第二,想把一个目录临时加入当前会话的PATH,执行$env:Path += ";C:\tools",只对当前窗口生效,关掉就没了,想持久生效还是得去“系统属性-环境变量”里改。第三,PowerShell里有几个命令别名和外部工具重名,最经典的是curl,在PowerShell里curl默认是Invoke-WebRequest的别名,行为完全不同,真要调用原生命令请写curl.exe;wget同理。

我在Windows上启动Elasticsearch的习惯步骤是:解压后切到bin目录,执行.\elasticsearch.bat,然后另开一个窗口用Test-NetConnection localhost -Port 9200验证是否就绪。启动Redis、启动Docker容器、查看容器日志,也都在同一个PowerShell窗口里完成。所以说,先把PowerShell本身用顺,Windows上几乎所有命令行工具都能统一管理起来。

4. 脚本与自动化:让PowerShell替你做重复劳动

4.1 反手一个C盘清理脚本

C盘清理是永恒话题。手动删临时文件太累,用图形界面里的磁盘清理又不够彻底。我习惯写一个PowerShell脚本,定期清一遍。先看空间占用:

Get-PSDrive C

然后清理临时目录、回收站,并统计释放了多少空间。完整脚本如下:

# Save as Clean-C.ps1,管理员运行 $before = (Get-PSDrive C).Used $paths = @( "$env:TEMP", "C:\Windows\Temp", "$env:LOCALAPPDATA\Temp" ) foreach ($dir in $paths) { Get-ChildItem -Path $dir -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } Clear-RecycleBin -DriveLetter C -Force -ErrorAction SilentlyContinue $after = (Get-PSDrive C).Used $freed = ($before - $after) / 1GB "清理完成,释放约 {0:N2} GB 空间" -f $freed

这段脚本做了三件事:读取清理前C盘已用空间,遍历三个临时目录删除文件,清空回收站,最后输出释放空间。关键点在$env:TEMP是当前用户临时目录的变量,C:\Windows\Temp是系统临时目录,清理后者需要管理员权限。每个删除命令都加了-ErrorAction SilentlyContinue,因为部分文件正被系统占用、删不掉很正常,没必要让脚本中断。

第一次跑之前建议改一下,把Remove-Item换成带-WhatIf的形式先看预演结果,确认它只会删临时目录里的内容,再真正执行。PowerShell脚本是纯文本,保存为.ps1文件后,在PowerShell窗口里输入.\Clean-C.ps1就能运行。

4.2 开机自启与定时任务怎么挂

很多人做“开机自启”第一反应是往启动文件夹里放快捷方式,但对PowerShell脚本或者后台任务来说,更好的方案有几个。先看最简单的方法:按Win+R,输入shell:startup,打开启动文件夹,在里面放一个快捷方式,目标设置为:

powershell.exe -WindowStyle Hidden -File "C:\Scripts\Clean-C.ps1"

这样开机登录后,脚本会在隐藏窗口里执行,不会弹个黑框吓人。

如果希望更可控,用计划任务。比如每天上午9点自动清理C盘,可以用PowerShell直接注册:

$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle Hidden -File C:\Scripts\Clean-C.ps1" $trigger = New-ScheduledTaskTrigger -Daily -At "09:00" Register-ScheduledTask -TaskName "DailyCleanup" -Action $action -Trigger $trigger -Force

计划任务比启动文件夹强的地方在于:可以指定触发时间、错开启动高峰、按天或按周重复。注意“不管用户是否登录都要运行”这个选项需要存账户密码,自己机器上不想折腾,就选“只在用户登录时运行”。

还有老派做法,往注册表Run键里写启动项。命令是New-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Run -Name MyScript -Value "powershell.exe -File C:\Scripts\Clean-C.ps1"。这方法简单,但问题是不好管理,开机启动过多还会拖慢登录速度,所以我的建议是:简单自启用启动文件夹,要定时、要条件就用计划任务。

4.3 批量操作:把“命令大全”变成“一条管道”

PowerShell最迷人的地方是管道和批量操作。正常你写10条命令做的事情,用管道往往1条搞定。举几个例子。

批量重启一组服务:

'Spooler','WSearch' | Restart-Service -ErrorAction SilentlyContinue

字符串数组通过管道一个一个传给Restart-Service,每条命令都作用于一个服务。这是最简单的批量。

扫描一个IP段里开放了哪些端口:

1..20 | ForEach-Object { $r = Test-NetConnection -ComputerName 192.168.1.1 -Port $_ -WarningAction SilentlyContinue if ($r.TcpTestSucceeded) { "Port $_ open" } }

这里用1..20生成了1到20的数字管道,ForEach-Object每次取一个数字放进$_,然后逐个做端口测试。批量扫描内网主机或验证服务端口时,这个模式非常实用。

批量改文件名也比较常见。比如把当前目录所有.txt文件改成.md:

Get-ChildItem *.txt | ForEach-Object { Rename-Item $_.FullName -NewName ($_.BaseName + ".md") }

管道传过来的是文件对象,所以$_有FullName、BaseName、Extension这些属性,直接拿来加工成新名字。这种写法比写for循环处理字符串再拼接路径要直观得多。

我的体会是,PowerShell的管道不要当成过场,它是整个脚本体系的灵魂。命令输出的对象带着属性,下一步命令可以直接引用,省掉大量解析文本的时间。

5. 高频报错与排查实录:踩过坑才不会慌

5.1 安装和升级报错:错误代码 -2146869246 怎么处理

遇到“安装程序无法安装 Windows PowerShell。错误代码为 -2146869246”的朋友不少。这个错误代码本质上是Windows Installer层的错误,常见原因有几类:系统更新不完整、.NET组件损坏、或者旧版本的PowerShell组件没有清理干净。

我的排查顺序一般是这样的:

  1. 先把系统更新打全。装新版PowerShell或升级5.1之前,确认.NET Framework 4.x已经装好。
  2. 用管理员身份打开PowerShell,依次执行DISM和SFC修复系统文件:
DISM /Online /Cleanup-Image /RestoreHealth sfc /scannow

这两个命令会把系统映像里的损坏文件修一遍,时间有点长,中途别关窗口。

  1. 临时退出安全软件后重试安装,装完再把安全软件开回来。
  2. 安装包务必从微软官方渠道下载。PowerShell 7优先用winget install或Microsoft Store,不要用第三方搬运的精简版。
  3. 还不行就先把旧的PowerShell相关组件卸载掉,重启系统再装。

Win7这类老系统装5.1之前,补丁需求更明显,建议先把系统更新打到最新。排查这个问题时,很多人会漏掉“DISM修复”这一步,其实它才是解决安装类错误最通用的手段。

5.2 乱码问题:中文显示成“锟斤拷”的真相

PowerShell中文乱码是另一大经典问题。大部分场景是控制台代码页不一致造成的。Windows PowerShell 5.1默认读取和输出文本时,会按系统ANSI编码来,简体中文环境就是GBK;而很多脚本文件、程序输出是UTF-8,两边对不上,中文就变成一堆乱码。

解决办法分几层。先临时切换代码页:

chcp 65001

把控制台切到UTF-8代码页。如果只是当前窗口有效,重开窗口就失效。想在脚本里固定输出编码,可以设置控制台编码:

[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

更隐蔽的坑在脚本文件的保存格式。Windows PowerShell 5.1对“无BOM的UTF-8”文件识别不好,用记事本或VS Code写脚本时,一定要把.ps1文件另存为“UTF-8 with BOM”格式;PowerShell 7.x对编码处理更现代,这个问题小很多。

如果你只是运行某个具体程序时看到乱码,比如Python输出中文乱码,先检查程序的输出编码设置,再回头看终端自身的编码。不要一上来就去改“系统区域设置里的Beta:使用Unicode UTF-8提供全球语言支持”,那个选项虽然能全局解决乱码,但可能让一部分老程序显示异常,谨慎使用。

5.3 其他高频报错速查表

把平时群里问得多的报错整理成一张速查表,方便收藏:

报错现象常见原因处理思路
无法加载文件,因为在此系统上禁止运行脚本ExecutionPolicy限制管理员执行Set-ExecutionPolicy RemoteSigned
xxx不是内部或外部命令命令不存在或未加入PATH用Get-Command检查,配置环境变量
拒绝访问权限不足用管理员身份重开PowerShell
gpedit.msc打不开系统版本不含组策略编辑器检查系统版本,家庭版建议用注册表替代
中文乱码控制台代码页不一致或脚本编码问题chcp 65001 + 脚本另存为UTF-8 with BOM
找不到模块或命令模块未安装或未导入Install-Module / Import-Module
端口被占用进程监听该端口Get-NetTCPConnection定位PID后结束进程
脚本执行到一半卡住命令在等待输入或网络超时Ctrl+C中断,查看报错定位

表格里最常被忽略的是“脚本执行到一半卡住”这一条。很多PowerShell新手以为脚本死循环了,其实是某个命令在等待确认或等待网络响应。比如Remove-Item删只读文件时不加-Force,会弹确认;Test-NetConnection连一个不通的IP,会等很久。遇到卡住先按Ctrl+C,再检查是不是少了参数。

补充一个“命令不存在”的排查技巧:报错之后先执行Get-Command xxx,如果返回空,说明命令真的不在当前环境里;如果返回了某个程序路径,但运行还是报错,多半是路径或参数问题。Windows自带的gpedit.msc打不开,常见原因是家庭版系统没有组策略编辑器,这种需求可以考虑用注册表替代,或者查微软官方文档确认该功能支持的版本。

最后再分享一个心态上的建议:PowerShell不是靠背命令学会的,是靠“猜命令+查帮助+跑一遍”学会的。常用命令就那几十条,剩下的大可以用Get-Help现查。执行破坏性操作前,多花10秒检查路径、多用-WhatIf预演,大多数坑都是可以避开的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询