规模化部署WinGet:winget-install的SYSTEM上下文支持与Intune/CI无人值守实战指南
【免费下载链接】winget-installInstall WinGet using PowerShell! Prerequisites automatically installed. Works on Windows 10/11 and Server 2019/2022.项目地址: https://gitcode.com/gh_mirrors/wi/winget-install
winget-install 是一个 PowerShell 脚本,能在 Windows 10/11 和 Server 2019/2022 上自动安装 WinGet 及其全部前置依赖。它对 SYSTEM 上下文与 Intune、CI 等无人值守场景做了专门适配——通过可判断的退出码与免交互流程,帮助 IT 管理员完成 WinGet 的规模化部署。
对单台电脑来说,装 WinGet 只需要一条命令;但当你要给 100 台、1000 台设备部署时,问题立刻变多:👇
- 没人坐在每台机器前点"确定"——脚本必须全程免交互;
- 部署平台(Intune、RMM、CI 流水线)需要明确的成败退出码来判断任务结果;
- 很多场景脚本是以 SYSTEM 身份运行的,而不是某个管理员用户——此时安装方式和验证方式都要换一套。
winget-install 正是为这三件事设计的。下面结合仓库源码,带你一步步把它用成"批量部署工具"。
一、为什么 WinGet 需要 winget-install 这个脚本?
WinGet 是微软官方的命令行包管理器,但它没有提供命令行安装器——官方文档里给的是手动下载 MSIX 包、逐个注册依赖的路径,这对单台机器还算可行,放到批量场景就完全不可行。
winget-install 把整个流程自动化了:自动识别 CPU 架构(x86/x64/arm/arm64)、自动检查操作系统兼容性、按系统版本决定安装哪套前置依赖,最后验证winget命令确实可用。项目对系统的支持范围(含 SYSTEM 场景)可在 README.md 的 Requirements 一节查到:
Requires PowerShell running with Administrator privileges -OR - execution under the SYSTEM context
也就是说,"以 SYSTEM 身份运行"是项目官方支持的一等公民场景,而不是侥幸能用。这一能力自 v5.1.0 引入、v5.2.1 完善,见 winget-install.ps1 的版本历史。
二、SYSTEM 上下文是如何被识别和处理的?
2.1 用 SID 而非账户名识别 SYSTEM
很多脚本用"SYSTEM" -eq $env:USERNAME判断系统账户,但账户名是本地化的——非英文系统上名字不同,判断就会失效。winget-install 改用安全标识符(SID)来识别,彻底避开语言问题:
# Check if running as SYSTEM $RunAsSystem = $false if ([System.Security.Principal.WindowsIdentity]::GetCurrent().User -match "S-1-5-18") { $RunAsSystem = $true }相关源码见 winget-install.ps1。S-1-5-18是本地系统账户在所有 Windows 语言版本下固定不变的 SID。
2.2 自动切换到"预配式"安装方法
普通用户身份下,脚本走 PowerShell Gallery 通道(安装Microsoft.WinGet.Client模块 +Repair-WinGetPackageManager -AllUsers)。但一旦$RunAsSystem为真,脚本会自动改走另一条路径——与 Server 2019 相同的路径:
- 从 WinGet 官方发布源下载
DesktopAppInstaller_Dependencies.zip,按需安装 UI.Xaml 与 VCLibs 依赖库; - 下载
winget的 MSIX 主包和许可证文件; - 使用
Add-AppxProvisionedPackage -Online将包预配到系统镜像(winget-install.ps1); - 按需静默安装 Visual C++ 运行库(
/quiet /norestart); - 修正访问权限并配置 PATH。
为什么 SYSTEM 场景必须换这条路径?因为以 SYSTEM 运行 PowerShell 时,NuGet 提供程序和用户会话环境不完整,Gallery 通道容易失败;而Add-AppxProvisionedPackage不依赖交互式用户环境,是微软官方为无桌面环境推荐的安装方式,天然适合批量部署。
2.3 以绝对路径验证 winget 是否装好
普通用户装完后,脚本用Get-Command winget验证命令是否可用。但 SYSTEM 会话通常没有加载到用户 PATH 里的环境,直接敲winget很可能"找不到命令"——即使装成功了。
为此脚本内置了Find-WinGet函数:直接在Program Files\WindowsApps下按通配符解析出winget.exe的完整路径,再以绝对路径执行winget -v来验证(winget-install.ps1)。验证逻辑集中在Get-WingetStatus中:
if ($RunAsSystem) { $wingetPath = Find-WinGet if ($null -ne $wingetPath) { $winget = & $wingetPath -v } } else { $winget = Get-Command -Name winget -ErrorAction SilentlyContinue }见 winget-install.ps1。
2.4 一个要记住的注意点
SYSTEM 身份完成的预配安装,注册到各用户环境的winget命令可能需要重启计算机或注销会话后才生效。脚本在结尾会主动提示这一点(winget-install.ps1):
Since this script is running under the SYSTEM context, you may need to restart the computer or session for the winget command to function as expected.
如果你的 Intune 流程允许,把"重启"作为部署的最后一步是最稳妥的。
三、无人值守核心:退出码与免交互设计
批量部署能不能"放手不管",取决于两点:脚本会不会卡在交互提示上、跑完后外部平台能不能判断成败。
3.1 全程无交互
脚本开头就把交互倾向全部关掉(winget-install.ps1):
$ProgressPreference = 'SilentlyContinue' # 关闭进度条(下载还更快) $ConfirmPreference = 'None' # 关闭一切确认提示安装 NuGet 提供程序等本会弹出"信任吗?"确认的步骤,也会被静默处理。配合默认不需要的任何参数,winget-install一条命令即可从零跑到完。
3.2 退出码是自动化平台的"生命线"
脚本统一通过ExitWithDelay函数收尾:成功退出 0,失败退出 1,覆盖权限不足、系统版本不兼容、winget 已安装(未加-Force)、下载失败等所有分支。
更关键的是针对irm ... | iex管道场景的退出码修复。管道执行时没有"脚本文件"上下文,普通的exit可能只断开管道而不把退出码传给宿主进程。v5.3.8 专门修复了这个问题:当检测到宿主是-Command/-EncodedCommand/-NonInteractive这类非交互宿主(正是 Intune、RMM、CI 的运行方式)时,脚本改用Exit $ExitCode,确保平台能拿到真实的进程退出码(winget-install.ps1,版本记录见 winget-install.ps1)。
这意味着你在 Intune 里不用解析日志猜结果——直接判断$LASTEXITCODE即可。
3.3 参数与全局变量速查
所有参数定义在 winget-install.ps1。批量场景下最需要记住的几个:
| 参数 / 变量 | 批量部署中的作用 |
|---|---|
-Force | 已装也强制重装/修复,适合"修复即部署"策略 |
-Wait/-NoExit | 仅在人工排错时观察输出用,自动化中不要用 |
-GHtoken | 提供 GitHub API 令牌,批量并发下载时规避 API 限流 |
-WingetVersion | 配合-AlternateInstallMethod锁定特定 winget 版本,实现基线一致 |
-AlternateInstallMethod | 主安装方法失败时的备用通道,也用于指定版本 |
$Force/$AlternateInstallMethod等全局变量 | 在irm \| iex一行式命令无法带参数时的替代开关,可写进 PowerShell 配置文件 |
完整参数说明见 README.md。
四、Intune 无人值守部署实战 🚀
Intune 的"脚本"策略默认就是以SYSTEM 身份在设备会话 0 中执行 PowerShell——正好落在 winget-install 的官方支持范围内。推荐做法:
第 1 步:把脚本放进 Intune 包
下载 winget-install.ps1 放入脚本包。脚本随附的assets/目录(assets/,含 7zip、aria2 等下载工具及 GetDLL.ps1)供组件下载环节使用,分发时建议一并保留目录结构。
第 2 步:Intune 脚本主体(保持极简)
powershell -ExecutionPolicy Bypass -File winget-install.ps1 -Force exit $LASTEXITCODE要点解析:
-File方式执行比irm | iex更容易在企业内网审计,且退出码传递最可靠;-Force让脚本在"已安装"时也会走完整修复流程,适合作为周期性合规策略;exit $LASTEXITCODE让 Intune 依据 0/1 精确判定成败并触发重试策略;- 全程无交互提示,设备端无需任何人值守。
第 3 步:失败分支
Intune 侧配置"非 0 退出码时重试",并配合-Debug参数留一档排错策略:
powershell -ExecutionPolicy Bypass -File winget-install.ps1 -Force -Debug第 4 步:收尾重启
如第 2.4 节所述,SYSTEM 安装的命令注册可能要重启后对用户可见。在 Intune 脚本中加一行shutdown /r /t 0 /c "winget deployment"(或使用维护窗口策略),或在部署后安排一次维护重启。
五、CI / 构建流水线场景实战
在 Windows CI Runner(Server 2019/2022 虚拟机很常见)上预装 WinGet,可以让后续流水线直接用它装工具链。典型片段:
# 幂等安装:已装则跳过,未装则自动装 winget-install if ($LASTEXITCODE -ne 0) { exit 1 } # 明确把失败抛给流水线CI 场景的三个加分项:
- 限流对抗:大量 Runner 并发拉取 GitHub 发布资源容易撞 API 限流。给脚本传
-GHtoken(在 CI 密钥库中配置)可大幅提升可靠性,该参数自 v5.3.1 引入,见 winget-install.ps1 的版本说明; - 版本基线:若希望全公司所有机器锁在同一 winget 版本(而非永远追最新),使用
-AlternateInstallMethod -WingetVersion x.y.z,两条参数即可实现一致的部署基线; - 更新自检:维护侧可定期跑
winget-install -CheckForUpdate,在不执行安装的前提下确认部署的脚本本身是否最新。
六、批量部署前检查清单 ✅
| 检查项 | 说明 |
|---|---|
| 系统版本 | Win10 需 1809+;Server 需 2019/2022/2025;Server 2016 及以下不支持 |
| 运行身份 | 管理员账户或SYSTEM(Intune 脚本默认为 SYSTEM,天然满足) |
| 网络 | 设备能访问 PowerShell Gallery 与微软发布源(脚本会静默下载多个依赖) |
| 退出码 | 平台侧必须消费$LASTEXITCODE,否则"看似跑完"≠成功 |
| 重启策略 | SYSTEM 预配安装后建议安排重启或注销 |
| 重试策略 | 脚本对临时性网络故障的通用建议就是"重跑一次",平台侧配置自动重试即可兜底 |
七、常见问题排查 🛠️
0x80073CF9注册失败:多见于以 SYSTEM 安装时的个别注册环节,脚本会给出明确警告;若后续winget仍不可用,用管理员账户重跑一次脚本(winget-install.ps1)。0x80073D02(资源被占用):通常是终端进程占用了 winget 相关资源,人工排错时加-ForceClose让脚本切到 conhost 并清理进程。- 装完提示"未检测到 winget 命令":SYSTEM 场景下等约 1 分钟或重启;仍不行则检查系统 PATH 是否含 winget 目录,重跑脚本并加
-Force会自动修正 PATH 与权限。 - 想深入看每一步:加
-Debug,脚本会输出 OS 检测、下载 URL、依赖版本等完整链路信息。
更多排错条目见 README.md 的 Troubleshooting 一节。
结语
单台机器装 WinGet 谁都会,难的是在一批机器上确定性地装好。winget-install 用三件小事把"难"变成了"平":SID 识别 SYSTEM 并自动切换预配安装、面向非交互宿主的可靠退出码、全程免交互的流程设计。把-Force、-GHtoken与重启策略组合进 Intune 或 CI,你就能得到一个可以长期运行、自动修复、结果可验证的 WinGet 规模化部署流水线。
【免费下载链接】winget-installInstall WinGet using PowerShell! Prerequisites automatically installed. Works on Windows 10/11 and Server 2019/2022.项目地址: https://gitcode.com/gh_mirrors/wi/winget-install
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考