对着几十台机器逐台点鼠标,是 IT 管理员最费时间的一类工作。本文给出 5 个可直接复制的 PowerShell 自动化脚本,覆盖批量创建用户、自动备份文件夹、检查磁盘空间、批量安装软件和生成系统报告这五类高频场景。
每个脚本的命令行为、参数含义和版本信息都整理自微软官方文档,链接放在对应句子之后,便于逐条核对。信息核验时点:2026-10-28(当前 LTS 版 PowerShell 7.6.6,PowerShell 7.6 发布于 2026-03-18)
本文要点
- 一句话定义:PowerShell 是微软的跨平台任务自动化方案,由命令行外壳、脚本语言和配置管理框架组成。
- 核心结论:5 个脚本分别对应 5 类日常运维场景,全部用官方命令拼装;PowerShell 7.6 的支持到 2028-11-14 截止。
- 适用场景:单机或工作组内的 Windows 重复性运维,例如新机器交付、定期备份、巡检出报告。
- 适用人群:会基本电脑操作、需要批量处理 Windows 运维任务的 IT 管理员。
- 短板/边界:本地账户命令不在 64 位系统上的 32 位 PowerShell 中提供;winget 仅支持 Windows 10 版本 1809(内部版本 17763)及更高版本;建账户和装软件这两类脚本要以管理员权限运行;脚本文件含中文时要按官方要求选好保存编码。
PowerShell 是什么?
PowerShell 是微软的跨平台任务自动化方案,由命令行外壳(command-line shell)、脚本语言和配置管理框架组成,可运行在 Windows、Linux 和 macOS 上(见官方概述)。和 Windows 自带的计算器、画图、记事本等图形工具不同,PowerShell 是面向管理员的命令行工具,属于Windows 自带工具里「系统管理」那一类。
和只收发文本的多数命令行工具不同,PowerShell 直接收发 .NET 对象,不需要再从文本输出里解析信息(见官方概述)。
对运维来说这意味着一件事:磁盘容量、用户列表、系统版本在脚本里都是带字段的对象,可以直接比较和筛选。
本文的 5 个脚本会用到三类命令,先把它们分清楚:
- 系统自带的 cmdlet(命令行小工具),例如查询磁盘的 Get-CimInstance。
- Windows 自带的命令行工具,例如复制文件的 robocopy。
- 独立安装的包管理器(package manager)winget,用来装软件。
如果你熟悉 Linux 环境下的自动化,会发现 PowerShell 的角色和 Linux Shell 脚本 类似——都是把重复操作写成脚本批量执行,只是语法和底层对象模型不同。
Windows PowerShell 5.1 和 PowerShell 7.6 该用哪个?
装机后先确认自己用的是哪条线:Windows PowerShell 5.1 是系统组件,PowerShell 7.x 是独立安装的跨平台版本。
下表的发布时间和支持截止日期照录自微软支持生命周期页面,Windows PowerShell 的支持随 Windows 操作系统本身的生命周期(见支持生命周期页)。
| 版本 | 发布时间 | 支持截止 | 定位 |
|---|---|---|---|
| Windows PowerShell 5.1 | 2016-08 | 随 Windows | 系统自带 |
| PowerShell 7.6 | 2026-03-18 | 2028-11-14 | 长期服务 |
| PowerShell 7.5 | 2025-01-23 | 2026-11-10 | 稳定版 |
| PowerShell 7.4 | 2023-11-16 | 2026-11-10 | 上一代长期服务 |
看这张表要注意一件事:7.5 和 7.4 的支持截止日都是 2026-11-10,距离本文核验只剩十三天,装这两个版本的机器很快就要换版本。官方页面的原话是 PowerShell 7.4.20 这个上一代长期服务版仍然受支持到 2026-11-10(见支持生命周期页)。
Windows PowerShell 5.1 于 2016 年 8 月发布,随 Windows 10 周年更新和 Windows Server 2016 一同提供(见支持生命周期页)。
截至 2026-10-28,支持生命周期页列出的当前稳定版是 PowerShell 7.5.11,当前长期服务版是 PowerShell 7.6.6(见支持生命周期页)。
微软不再支持低于 5.1 的 Windows PowerShell 版本(见支持生命周期页)。
新写的脚本建议以 PowerShell 7.6 为目标环境,服务器上没装 7.x 时,本文脚本在 5.1 下也能执行,细节见文末常见问题。
脚本一:批量创建用户怎么做?
批量建账户的思路是把名单放进 CSV(逗号分隔值)文件,脚本逐行读取并调用 New-LocalUser,避免一台台机器手工点。
New-LocalUser 的官方说明是创建本地用户账户,密码参数要求传入安全字符串(SecureString)形式(见New-LocalUser 文档)。
官方示例用 Read-Host -AsSecureString 录入密码并存进变量,再传给 New-LocalUser 的 -Password 参数(见New-LocalUser 文档)。
操作步骤:
- 准备名单文件 new-users.csv,列名固定为 Name、FullName、Description、Group,Group 列留空表示不加组。
- 右键 PowerShell 图标选「以管理员身份运行」,在打开的控制台里执行脚本,屏幕会提示输入初始密码,输入后回车。
- 脚本按行创建账户并按 Group 列加入本地组,控制台输出每个账户的名称、启用状态等字段。
名单文件格式如下,用记事本保存即可,保存时编码选 UTF-8:
Name,FullName,Description,Group
zhangsan,张三,销售部,Users
lisi,李四,技术部,Remote Desktop UsersGroup 列要写这台电脑上已经存在的本地组名,不确定的话先跑一句 Get-LocalGroup 看看清单。实测写一个不存在的组名(比如 IT-Staff)时,Add-LocalGroupMember 会报「未找到组 IT-Staff。」,而加组是建完账户之后的第二条语句,报错不会中断循环,后面的行照样处理;也就是说账户建成了、组没加上,补组要自己再单独执行一次。
名单文件的编码也别选错。官方说明在 Windows PowerShell 5.1 里,Import-Csv 遇到没有 BOM 的文件时按 UTF-8 读取(见字符编码说明),所以存成 UTF-8 的名单能读对;实测把同一份名单存成 ANSI(中文 Windows 上的 GBK)再读,FullName 和 Description 全部变成乱码,会带着替换符写进账户。这一点下面脚本三还会再遇到一次。
批量创建脚本:
# 从 CSV 名单批量创建本地账户并按需加入本地组
$users = Import-Csv -Path .\new-users.csv
$password = Read-Host -AsSecureString -Prompt "输入新账户的初始密码"
foreach ($u in $users) {
New-LocalUser -Name $u.Name -Password $password -FullName $u.FullName -Description $u.Description
if ($u.Group) {
Add-LocalGroupMember -Group $u.Group -Member $u.Name
}
}三点边界要留意。第一,Microsoft.PowerShell.LocalAccounts 模块在 64 位系统上的 32 位 PowerShell 里不提供(见New-LocalUser 文档)。这组命令的官方文档也只有 Windows PowerShell 5.1 那一个视图,按 7.6 去访问会被自动退回 5.1,本文实测过这一点。
第二,这类操作要管理员权限。实测在未提升权限的 PowerShell 5.1 控制台里调用 New-LocalUser,直接返回「拒绝访问。」,错误 ID 是 AccessDenied,一个账户也不会被创建。
第三,Add-LocalGroupMember 把用户或组加入本地安全组(local security group),官方文档提醒本地 Administrators 组的成员对该计算机拥有完全控制权限,应限制该组人数(见Add-LocalGroupMember 文档)。
风险提示:批量脚本里不要写死明文密码,本文用交互输入的方式避免密码落盘。
域环境里建域账户用的是另一个命令:New-ADUser 的官方说明是创建 Active Directory 用户(见New-ADUser 文档)。
ActiveDirectory 模块随 Windows Server 提供,它的支持走 Windows 支持生命周期(见支持生命周期页)。
脚本二:文件夹自动备份怎么做?
备份文件夹建议交给 robocopy,官方文档对它的定位是把文件数据从一个位置复制到另一个位置(见robocopy 文档)。
本脚本每天生成一个带日期的备份目录,复制结果写进日志,失败时报告退出码。
先看各参数的官方含义:
- /E 复制子目录并包含空目录;/Z 用可重启模式复制,中断后能从断点继续(见robocopy 文档)。
- /MT:8 表示多线程复制,官方说明线程数取值为 1 到 128,默认值是 8(见robocopy 文档)。
- /LOG: 把状态输出写入日志文件并覆盖原有日志,/LOG+: 则是追加(见robocopy 文档)。
备份脚本:
# 每次运行都生成带日期的备份目录和日志
$stamp = Get-Date -Format "yyyyMMdd"
$src = "D:\Data"
$dst = "E:\Backup\Data-$stamp"
$logDir = "E:\Backup\logs"
$log = "$logDir\Data-$stamp.log"
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
robocopy $src $dst /E /Z /MT:8 /R:3 /W:5 /LOG:$log
if ($LASTEXITCODE -ge 8) {
Write-Error "robocopy 复制失败,退出码 $LASTEXITCODE"
}建日志目录这一行不是可选的。robocopy 会自动创建目标目录,这一步实测过(源目录里放一个文件,指向还不存在的目标目录跑一次,文件正常落到新建的目标目录里),但它不会替日志文件创建上级目录。实测把 /LOG: 指到一个不存在的目录,也就是首次运行时 E:\Backup\logs 还没建的情况,robocopy 还没开始复制就报「错误 3 (0x00000003) 正在打开日志文件 …」,随后提示 /LOG: 这个参数无效,退出码 16;16 也满足上面「大于等于 8」的判断,但报出来的是打日志失败而不是复制失败,容易被当成脚本写错了。New-Item 带 -Force 能一次建出多级目录,这一步也实测过。
退出码的判断依据是官方说明:任何大于等于 8 的值都表示复制过程中至少发生过一次失败(见robocopy 文档)。本机实测的还有两个具体值:正常复制完是 1,源目录写错、指向了一个不存在的目录时是 16。
风险提示:robocopy 的 /MIR 等于 /E 加上 /PURGE,会删除目标位置里源目录中已不存在的文件,误用会造成数据丢失(见robocopy 文档)。
想让备份每天自动跑,把这个脚本交给系统自带的定时任务功能在指定时间执行即可,跑通手动版本后再挂定时。
脚本三:磁盘空间检查怎么做?
巡检磁盘空间可以用 WMI(Windows Management Instrumentation,Windows 管理规范)类 Win32_LogicalDisk,官方文档说明它代表解析到实际本地存储设备的数据源(见Win32_LogicalDisk 文档)。
这个类的 DriveType 属性取值 3 表示 Local Disk,也就是本地磁盘(见Win32_LogicalDisk 文档)。
FreeSpace 属性以字节为单位给出磁盘上的可用空间(见Win32_LogicalDisk 文档)。
磁盘检查脚本:
# 列出本地固定磁盘的容量,并对剩余空间不足的磁盘给出警告
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" |
ForEach-Object {
[PSCustomObject]@{
盘号 = $_.DeviceID
剩余GB = [math]::Round($_.FreeSpace / 1GB, 2)
总容量GB = [math]::Round($_.Size / 1GB, 2)
}
} | Format-Table
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" |
Where-Object { $_.FreeSpace -lt 20GB } |
ForEach-Object { Write-Warning "$($_.DeviceID) 剩余空间不足 20 GB" }使用方法分三步:
- 把脚本保存为 check-disk.ps1,在 PowerShell 控制台执行,屏幕会列出各盘符的剩余容量和总容量。
- 有磁盘低于阈值时,屏幕输出黄色警告并带上盘符。
- 把 20GB 阈值改成你自己的标准,巡检机房服务器时可以按盘符逐个核对。
本机实测的输出是这样一张表,盘符、剩余容量、总容量三列一目了然:
盘号 剩余GB 总容量GB
---- ------ --------
C: 110.39 178.16
D: 226.23 295.82
E: 463.24 1028
F: 238.38 4561.03保存这个文件时有一步容易踩坑:脚本里的 [PSCustomObject] 用了「盘号」「剩余GB」这样的中文键名。微软有一页专门讲字符编码,官方写法是「如果需要在脚本里使用非 ASCII 字符,就把脚本存成带 BOM 的 UTF-8;没有 BOM 时,Windows PowerShell 会按传统 ANSI 代码页来解释你的脚本」(见字符编码说明)。
本机实测和官方说法对得上:同一份内容存成不带 BOM 的 UTF-8,Windows PowerShell 5.1 还没开始运行就报两条解析错误,提示哈希表的键后面缺少「=」运算符、语句块缺少右「}」;改成带 BOM 的 UTF-8,或者用记事本另存成 ANSI,两份都能正常跑出上面那张表。PowerShell 7 不带 BOM 也读得对,因为官方说明它把 UTF-8 当作输入输出的默认编码(见字符编码说明)。不想折腾编码的话,把这三个键名改成 Drive、FreeGB、SizeGB,脚本就变成纯 ASCII,怎么存都不会出问题。
这个脚本只读取信息,不改动系统,适合作为第一个上手练习。本机(Windows 10 自带的 Windows PowerShell 5.1)实测整段跑完约一百多毫秒,重复执行时降到几十毫秒,磁盘数量再多也感觉不到等待。
脚本四:批量安装软件怎么做?
批量装软件用 winget,官方文档写明它是面向 Windows 10、Windows 11 和 Windows Server 2025 的命令行工具,用于发现、安装、升级、移除和配置应用(见winget 概述)。
winget 随 App Installer(应用安装程序)提供,官方注明命令行工具仅支持 Windows 10 版本 1809(内部版本 17763)及更高版本(见winget 概述)。
winget install 命令安装指定应用,官方文档里的用法是先用 winget search 确定要装的应用(见install 命令文档)。
其中 --id 把安装限定到指定的包 ID,-e 要求精确匹配,--silent 以静默模式运行安装程序并隐藏所有界面(见install 命令文档)。
--accept-package-agreements 接受包安装程序弹出的许可协议,从而去掉交互提示(见install 命令文档)。
批量安装脚本:
# 按清单静默安装软件,包 ID 用 winget search 查询后填入
$apps = @(
"7zip.7zip"
)
foreach ($app in $apps) {
winget install --id $app -e --silent --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
Write-Warning "$app 安装失败,winget 退出码 $LASTEXITCODE"
}
}操作步骤:
- 运行 winget search 加软件关键词,把结果里的包 ID 填进 $apps 清单。
- 执行脚本,静默安装期间不会弹出安装界面。
- 某个包装不上时,屏幕输出黄色警告和对应的退出码。
安全提示:官方文档提醒,以管理员身份运行命令行时要格外小心,只安装自己信任的应用(见winget 概述)。
脚本五:系统报告怎么生成?
交接机器或做资产盘点时,用 Get-ComputerInfo 一次取回系统概况最省事。
Get-ComputerInfo 的官方说明是把系统属性和操作系统属性汇总成一个对象返回,并且该命令只在 Windows 平台提供(见Get-ComputerInfo 文档)。
它的 -Property 参数支持通配符,官方示例用 -Property "*version" 只取版本类属性(见Get-ComputerInfo 文档)。
ConvertTo-Html 的官方说明是把 .NET 对象转换成浏览器可显示的 HTML(超文本标记语言)网页(见ConvertTo-Html 文档)。
报告脚本:
# 生成一份 HTML 系统概况报告
$report = Get-ComputerInfo -Property "Windows*", "Os*", "Cs*", "Bios*"
$html = $report | ConvertTo-Html -Title "系统报告" -PreContent "生成时间 $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
$html | Out-File -FilePath .\system-report.html操作步骤:
- 在 PowerShell 控制台执行脚本,命令跑完后当前目录多出 system-report.html。
- 用浏览器打开该文件,能看到 Windows 版本、系统版本等属性组成的表格。
- 需要纸质留档时,直接在浏览器里打印这份报告。
本机实测的耗时分布值得一说:整段脚本里慢的只有取信息那一步,Get-ComputerInfo 取这 4 组属性花了约 3 秒,后面转 HTML 再写文件只花十几毫秒,生成的报告约 8.6 KB。带通配符过滤并不是为了省时间,而是为了让报告短一点——实测过滤后仍有 166 个属性,不加过滤取全量也才 182 个。
脚本里 -Property "Windows*", "Os*", "Cs*", "Bios*" 这种写法靠的是逗号:第一个字符串后面的逗号会把四个字符串拼成一个数组,一起交给 -Property。本机实测确实四组都取到了,按前缀数下来分别是 Windows 开头 11 个、Os 开头 63 个、Cs 开头 61 个、Bios 开头 31 个,合计 166 个,和上面那句里的数字对得上。
跑脚本前要先过哪一道安全关?
PowerShell 的执行策略(execution policy)是安全功能,控制 PowerShell 加载配置文件和运行脚本的条件(见执行策略文档)。
官方文档明确写道,执行策略不是安全边界,只是纵深防御,因为不能跑脚本的用户仍可以把脚本内容逐条敲进命令行(见执行策略文档)。
文档把 Default 策略描述为对 Windows 客户端和服务器都设为 RemoteSigned(见执行策略文档)。
RemoteSigned 的要求是:从互联网下载的脚本和配置文件要有可信发布者的数字签名,本地编写且未从互联网下载的脚本不需要签名(见执行策略文档)。
除执行策略外,再记两条安全习惯:
- 脚本里的账户操作用交互输入取密码,不要把密码写进脚本文件。
- 安装类脚本涉及管理员权限,运行前确认清单里的每个包都来自可信来源。
常见问题
脚本应该从哪里运行?
在 PowerShell 控制台里执行 .ps1 文件,而不是在资源管理器里双击。执行策略正是控制脚本能否运行的开关,默认的 RemoteSigned 对本地编写的脚本不要求签名(见执行策略文档)。若运行时被拦下,先用 Get-ExecutionPolicy 查看当前策略,确认策略范围和组织的管理规定后再调整,不要一上来就改成 Bypass。
Windows PowerShell 5.1 能运行这 5 个脚本吗?
命令层面可以,本文脚本用到的命令在 5.1 环境下都有对应能力。本机(Windows 10 自带 5.1)逐个实测的结论更具体:
- 脚本三、脚本五原样跑通。脚本三整段跑完一百多毫秒,脚本五取那 4 组属性约 3 秒,转 HTML 加写文件只花十几毫秒。
- 脚本二的 robocopy 那行用临时目录实测过,/L 干跑和正式复制都正常,退出码判断也验证过;文中的 D 盘到 E 盘路径换成你自己的即可。
- 脚本一在本机只做到参数名校验,没有真建账户:非管理员权限下 New-LocalUser 直接返回拒绝访问。
- 脚本四没有真装软件,因为装完会留下程序。本文只核对了用到的 5 个开关确实存在于本机 winget 的 install 帮助里。
两处编码前提要记住。脚本三用了中文列名,.ps1 要存成带 BOM 的 UTF-8,否则 5.1 解析阶段就报错;脚本一的 new-users.csv 要存成 UTF-8,存成 ANSI 时 Import-Csv 读出来的中文全是乱码。
Get-ComputerInfo 的官方文档写明该命令于 Windows PowerShell 5.1 引入(见Get-ComputerInfo 文档)。
robocopy 和 winget 是独立的命令行工具,其中 winget 随 App Installer 提供(见winget 概述)。
需要注意的是,微软不再支持低于 5.1 的 Windows PowerShell 版本,长期维护的脚本建议以 PowerShell 7.6 为基准(见支持生命周期页)。
winget 命令找不到该怎么处理?
先确认系统满足前提:winget 随 App Installer 提供,仅支持 Windows 10 版本 1809(内部版本 17763)及更高版本(见winget 概述)。
官方文档写明,首次以用户身份登录 Windows 后由 Microsoft Store 异步完成注册;如果登录后 winget 仍不可用,可在 PowerShell 运行 Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe 请求注册(见winget 概述)。
下一步怎么做?
- 先跑脚本三的磁盘检查,它只读取信息,用来验证你的 PowerShell 环境和执行策略是否正常。保存这个文件时记得选带 BOM 的 UTF-8,否则脚本三会因为中文列名在 Windows PowerShell 5.1 上报解析错误。
- 备份脚本第一次试运行时加 /L 参数,官方说明该参数只列出文件而不复制、不删除、不改时间戳,确认清单无误后再正式备份(见robocopy 文档)。本机实测这条干跑退出码是 1,不触发脚本里的失败分支。
- 建用户脚本先在测试机上用两三行 CSV 跑一遍,控制台要用管理员权限打开,确认列名和分组名称都符合预期,再应用到生产机器。
- 装软件前用 winget search 确定应用、winget show 查看将要选用的安装包详情(见install 命令文档)。
各命令的完整参数以官方文档为准:
- robocopy 的完整参数见robocopy 文档。
- New-LocalUser 的完整参数见New-LocalUser 文档。
- winget install 的完整参数见install 命令文档。
本文数据核验于 2026-10,以官方 Release Notes/文档为准。