WinGet 基础
WinGet 是微软官方的 Windows 包管理器,一句话概括:用一行命令把软件装好、升好、卸干净,不用点"下一步"。
winget install Git.Git
以前装软件是「搜官网 → 找下载链接 → 下 exe → 装 → 勾掉「创建桌面快捷方式」→ 下一步 → 完成」。有了 winget 之后,上面那一整串就是一行命令,而且卸载、升级、批量重装也是一行。
本文为基础篇,目标是:装好 winget → 学会搜/装/看/升/卸 → 能一条命令配置完一台新机器。
本文内容对照 WinGet v1.29(客户端版本会随「应用安装程序」自动更新,用 winget --version 查看)。
目录
- winget 是什么
- 安装与自检
- 核心概念:ID、源、包
- 搜索 search
- 查看详情 show
- 安装 install
- 已装列表 list
- 升级 upgrade
- 卸载 uninstall
- 下载离线包 download
- 命令与参数速查
- 实战:一台新机器的初始化脚本
- 常见问题
1. winget 是什么
它由三部分组成
| 部分 | 说明 |
|---|---|
| winget.exe 客户端 | 你在终端里敲的那个命令,随系统自带 |
| 包索引(source) | 一堆描述「哪个软件、多少版本、从哪下载、哈希是多少」的清单文件 |
| 包仓库(repository) | 存放索引的服务,winget-pkgs 社区仓库 + 微软商店 |
关键认知:winget 自己不存任何软件,它只是一个「读清单 + 下载 + 调用安装器」的工具。真正装东西的是软件官方的安装器(exe / msi / msix)。这也是为什么 winget 装出来的软件和官网下载装出来的是同一个软件。
管理员权限的影响
| 情况 | 表现 |
|---|---|
| 普通 PowerShell 窗口 | 装「需要管理员」的软件时,弹 UAC 让你确认;你若点了取消,安装就失败 |
| 以管理员身份运行的 PowerShell | 不会有 UAC 弹窗直接装上,但也意味着你在给整台机器装东西 |
新手常见困惑:「为什么我明明是管理员,winget 还要弹 UAC?」——因为 winget 默认是以用户身份运行的,安装器自己再提权。开一个管理员 PowerShell 就能跳过这一步。
和 Scoop / Chocolatey 的区别
| WinGet | Scoop | Chocolatey | |
|---|---|---|---|
| 出品方 | 微软官方 | 社区 | 社区(商业公司维护) |
| 仓库来源 | 社区维护 manifest | 社区 + 官方 GitHub Releases | 社区 + 部分官方源 |
| 权限 | 多数走官方安装器,常需 UAC | 默认装到用户目录,无需管理员 | 安装器为主,常需管理员 |
| 适用 | 想装「和官网一模一样的正式版」 | 想装「命令行工具」并保持用户级干净 | 企业批量管控(付费功能多) |
一句话:装开发工具优先 Scoop(免管理员),装桌面软件优先 winget(和官网一致)。两个可以共存。
2. 安装与自检
系统要求
- Windows 10 1809(build 17763) 及以上,或 Windows 11
- Windows Server 2025 支持;Server 2019 / 2022 属于实验性支持
winget 从哪来
它不是一个单独的软件,而是**「应用安装程序」(App Installer)**这个系统组件带出来的命令行客户端。系统自带,一般不用装。
打开「Microsoft Store」→ 搜索 应用安装程序 / App Installer → 更新到最新版本,就能拿到最新的 winget。
如果你的机器上压根没有(比如精简版系统、LTSC、刚装完还没登录过):
- 商店里搜 App Installer 安装;
- 或者手动注册一次(首次登录新系统时 winget 迟迟不出现,多半是这个原因):
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
自检三连
winget --version # 版本号
winget --info # 完整信息:系统版本、源、协议、组策略、许可证链接
winget --help # 命令列表
winget --info 的输出值得看一眼——如果发现某个源不是你配的,说明电脑上有组策略(GPO)在管控 winget,公司电脑尤其要留意:
源
winget (默认) https://cdn.winget.microsoft.com/cache
msstore (默认) https://storeedgefd.dsx.mp.microsoft.com/v9.0
winget.exe 找不到?
命令提示「不是内部或外部命令」时,加到 PATH:
Win + R→ 输入shell:AppsFolder回车;- 找到「应用安装程序」→ 右键 →「创建快捷方式」,快捷方式会落在桌面;
- 右键该快捷方式 →「属性」→ 复制「目标」一栏的完整路径(通常在
C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\AppInstaller\winget.exe); - 把这个目录加到「系统属性 → 环境变量 → 用户变量 → Path」。
每次更新「应用安装程序」后版本文件夹名里的哈希会变,所以更稳妥的做法是别手动加 PATH,而是去 Microsoft Store 更新组件。
3. 核心概念:ID、源、包
包的 ID 长什么样
winget search vscode
输出里每一行都有一个 ID:
名称 标识 来源 版本
Visual Studio Code Microsoft.VisualStudioCode winget 1.95.0
VSCodium Anysphere.VSCodium winget 1.95.0
ID 的格式是 发布者.应用名,全局唯一。Microsoft.VisualStudioCode 和 Anysphere.VSCodium 是两个完全不同的软件(前者是微软官方版,后者是 VSCodium 社区版)。
用 ID 安装比用名称可靠得多,原因:
- 名称是「显示用」的,同一个软件在不同语言下可能不一样;
- 名称可能重名,
search code会返回一堆结果; - ID 精确,脚本里不会因为搜索结果排序变化而装错东西。
直接敲
winget install vscode也可以(winget 会自己去搜),但在脚本里必须用 ID +-e。
两个(实际是三个)默认源
| 源名 | 是什么 | 注意 |
|---|---|---|
winget | WinGet 社区仓库(manifest 由社区贡献) | 主力源,绝大多数软件在这里 |
msstore | 微软商店 | ID 是一串大写字母数字(商店的 PFN),不需要 -e |
winget-font | 社区字体仓库 | 默认是「显式」源,必须 --source winget-font 才会被搜索到 |
winget source list # 看当前有哪些源
为什么会出现「找到多个」
winget install chrome
如果 winget 源和 msstore 源里都有叫 Chrome 的东西,winget 会列出候选让你选。在脚本里这是致命的,所以要加 --source winget 限定。
4. 搜索 search
winget search <关键词>
匹配范围是名称、ID、描述、moniker、标签的大小写不敏感子串。不支持通配符——写 winget search fire* 是搜不到 Firefox 的。
常用过滤参数
| 参数 | 作用 | 例 |
|---|---|---|
--id | 只搜 ID | winget search --id Git.Git |
--name | 只搜名称 | winget search --name "Visual Studio Code" |
--moniker | 只搜 moniker | winget search --moniker chrome |
--tag | 按标签过滤 | winget search --tag editor |
--cmd / --command | 按「装完能敲的命令」搜 | winget search --command python |
-s / --source | 限定源 | winget search vscode -s msstore |
-n / --count | 限制条数(1–1000) | winget search browser -n 10 |
-e / --exact | 精确匹配(区分大小写) | winget search Git.Git --id -e |
--versions | 直接列出所有可用版本 | winget search vscode --versions |
三个特别实用的搜法
① 按命令搜(最省事)
不知道包名只记得命令名时:
winget search --command rg # 谁提供了 ripgrep
winget search --command node
② 列出全部包
winget search -q ""
新版本必须显式给空查询字符串。PowerShell 里要转义引号:
winget search -q "`""
③ 只搜某个源
winget search "Visual Studio Code" -s msstore
5. 查看详情 show
winget show --id Microsoft.VisualStudioCode
输出包含:发布者、简介、主页、许可证、安装器类型、依赖、可用版本、安装大小。
安装前拿不准「这玩意装到哪、有没有捆绑流氓软件、要多少空间」时,先 show 一下。
winget show --id Microsoft.PowerToys --versions # 所有历史版本
想看某个包「到底用哪条安装命令装我」,看仓库里的 manifest 原文最快,见进阶篇。
6. 安装 install
三种指定目标的方式
winget install vscode # 按查询串(winget 自己搜)
winget install --name "Visual Studio Code" # 按名称
winget install --id Microsoft.VisualStudioCode # 按 ID
推荐第三种,并加 -e:
winget install --id Microsoft.VisualStudioCode -e
-e(--exact)是精确匹配,区分大小写。它的真正价值在脚本里:确保不会因为将来仓库新增了重名包而行为变化。
一次装多个
winget install Microsoft.VisualStudioCode Microsoft.PowerShell Git.Git
按顺序依次安装,不是并行。配新机器时很方便。
常用参数
| 参数 | 作用 | 例子 |
|---|---|---|
-v / --version | 装指定版本(不给就装最新) | --version 0.91.1 |
--scope | 安装范围 | --scope user |
-a / --architecture | 架构 | -a x64 / -a arm64 |
--installer-type | 强制选某类安装器 | --installer-type zip |
-l / --location | 装到指定目录 | -l "D:\Tools\PowerToys" |
-h / --silent | 静默安装,不显示任何界面 | |
-i / --interactive | 强制显示安装界面 | |
--no-upgrade | 已装了就跳过(脚本幂等的关键) | |
--force | 忽略非安全类问题继续执行 | |
--allow-reinstall | 已安装也强制重装 | |
--uninstall-previous | 升级时先卸掉旧版本 | |
--custom | 追加传给安装器的参数 | --custom "/LOG D:\log.txt" |
--override | 直接覆盖安装器命令行 | --override "/quiet /norestart" |
--skip-dependencies | 跳过依赖检查 | |
--allow-reboot | 允许在需要时重启 | |
-r / --rename | 重命名可执行文件(仅 portable) |
一个能直接复制走的安装命令
winget install --id Microsoft.VisualStudioCode -e --silent `
--accept-package-agreements --accept-source-agreements --disable-interactivity
这四个参数是写自动化脚本的标准配置,后面会详细解释。
许可证协议
有些软件安装前会弹「是否同意许可协议」。交互式使用时点确认即可,脚本里加:
--accept-package-agreements # 接受软件本身的协议
--accept-source-agreements # 接受源(仓库)的使用条款
两个是分开的:--accept-package-agreements 只管软件自己的许可,不管仓库的条款。
日志
winget install --id Git.Git -o D:\logs\git-install.log
不指定 -o 时日志默认在:
%LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir\
winget --logs 直接打开这个目录。
7. 已装列表 list
winget list # 所有 winget 能识别的已装软件
winget list --name "Code" # 按名称过滤
winget list --upgrade-available # ★ 只看「有新版可升」的
--upgrade-available 是最常用的一个:它只列出需要升级的包,不用自己肉眼比对。
--include-unknown 的意义
winget list --upgrade-available --include-unknown
默认情况下,winget 只认自己仓库里有的包。手工装的、官网下载的、系统自带的,ID 对不上,winget 就不管它们。
加了 --include-unknown 之后,已经装在机器上、但仓库里找不到的包也会列出来,状态标记为「无升级 / 未知」。
- 用它做软件资产盘点很好用(能看见机器上到底装了什么);
- 但用
winget upgrade --all时要小心:--all会把能升级的全部升一遍,包含那些原本没被 winget 管理的包,需要先确认。
显示 ID 列
winget list --name "Code" --source winget
list 默认只显示「名称 / 版本 / 可用版本」。遇到重名软件想看 ID 时,加上 -e 再看,或者直接去「应用和功能」对照。
8. 升级 upgrade
winget upgrade # 交互式:列出所有可升级的,逐个问你
winget upgrade --all # ★ 全部升级,不再逐个询问
winget upgrade --id Git.Git -e # 只升一个
--all 的两个注意点
- 它会升级所有「有新版且 winget 认识」的包,包含你从官网手工装的那批(只要 ID 能对上)。
- 加上
--accept-package-agreements --disable-interactivity才是无人值守的完整形态。
「刚装完就提示有新版」
这个现象很常见,原因基本是以下几种:
| 原因 | 说明 | 怎么办 |
|---|---|---|
| 预览版 | 仓库里存在更高版本的预发布包 | winget show --id X 看版本号是否是带 -preview 之类后缀 |
| 索引没更新 | 本地缓存的清单还是旧的 | winget source update 后再看 |
| 多源版本号不一样 | msstore 源的版本和 winget 源不一致 | winget upgrade --id X -s winget 限定源 |
| 装的是非最新版 | 你用 --version 锁过版本 | winget list --id X 对比「已装 / 可用」 |
| 架构不对 | 装了 x86,系统在跑 x64,两边版本号独立 | 卸载重装正确架构 |
最快的诊断姿势:
winget list --id XXX # 看「已装」和「可用」两列差多少
winget show --id XXX # 看仓库里到底有哪些版本
9. 卸载 uninstall
winget uninstall --id Git.Git -e
winget uninstall --name "Visual Studio Code" -e
行为和 install 一样:优先用 manifest 里声明的卸载信息(ProductCode / UninstallSwitch),能干净地卸掉。做不到时退回到调用软件自己的卸载器。
同样支持一次卸多个 ID。
10. 下载离线包 download
不安装,只把安装器下载到本地:
winget download --id Microsoft.VisualStudioCode -d D:\installers
| 参数 | 作用 |
|---|---|
-d / --download-directory | 下载目录(不给就下载到当前目录) |
--skip-dependencies | 不下依赖 |
--skip-license | 跳过许可文件 |
--version / --architecture / --scope / --installer-type | 同 install |
用途:给内网机器准备离线安装包、在服务器上装没有浏览器的软件。
11. 命令与参数速查
命令总览(v1.29)
| 命令 | 作用 | 别名 |
|---|---|---|
search | 搜索可安装的软件 | find |
show | 查看包详情 | |
install | 安装 | add |
list | 列出已安装 | |
upgrade | 升级 | |
uninstall | 卸载 | remove |
download | 只下载安装包 | |
pin | 管理版本锁定 | |
export | 导出已装列表 | |
import | 按文件批量安装 | |
source | 管理源 | |
configure | 按 YAML 把机器配置到目标状态 | |
repair | 修复损坏的软件 | fix |
hash | 计算安装包 SHA256 | |
validate | 校验本地 manifest | |
settings | 打开 settings.json | |
features | 查看实验性功能开关状态 | |
error | 查错误码含义 | |
completion | 生成 shell 补全脚本 |
全局参数
这些参数任何子命令都能加:
| 参数 | 作用 |
|---|---|
--info | 详细信息(含组策略) |
--logs | 打开日志目录 |
--verbose | 详细日志 |
--nowarn | 屏蔽警告 |
--disable-interactivity | 禁止一切交互提问 |
--proxy | 本次执行使用的代理 |
--no-proxy | 本次执行不走代理 |
-? / --help | 帮助(每个子命令都能单独 --help) |
--wait | 执行完等回车再退出(调试时用,脚本里千万别加) |
winget error 是个被严重低估的功能:
winget error 0x8A150011
直接输出错误码的中文/英文说明。遇到看不懂的 0x8A1500xx,先敲这一条。
12. 实战:一台新机器的初始化脚本
把基础命令组合起来,就是一份可复用的「装机脚本」。
最小可用版
# winget-init.ps1 —— 新机器一键装环境
$ErrorActionPreference = 'Continue'
# 脚本标准四件套
$commonArgs = @(
'--exact'
'--silent'
'--accept-package-agreements'
'--accept-source-agreements'
'--disable-interactivity'
)
$packages = @(
'Microsoft.VisualStudioCode'
'Git.Git'
'Microsoft.PowerShell'
'Python.Python.3.12'
'NodeJS.LTS'
'7zip.7zip'
'Notepad++.Notepad++'
'Google.Chrome'
)
foreach ($pkg in $packages) {
Write-Host "==> installing $pkg" -ForegroundColor Cyan
winget install --id $pkg @commonArgs
if ($LASTEXITCODE -ne 0) {
Write-Warning "$pkg failed with exit code $LASTEXITCODE"
}
}
Write-Host "`nAll done." -ForegroundColor Green
为什么用 --exact 而不是 -e:PowerShell 的参数解析里 -e 可能被当成别的,--exact 更明确。
为什么加 --no-upgrade 可以做到真正幂等:见下面的进阶版。
幂等版(可以反复跑)
# 已经装了就跳过
foreach ($pkg in $packages) {
winget install --id $pkg @commonArgs --no-upgrade
}
--no-upgrade 的语义是「如果已装过(哪怕版本旧),直接跳过,不做升级也不报错」。这让脚本可以每周定时跑,只补装缺失的软件。
升级全部
winget upgrade --all `
--accept-package-agreements `
--disable-interactivity
备份一份已装清单
winget export -o D:\backup\apps.json --include-versions
新机器直接导入:
winget import -i D:\backup\apps.json
细节(版本锁定、
--ignore-versions、源优先级、脚本化注意事项)见进阶篇。
13. 常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
winget 不是内部或外部命令 | App Installer 没更新 / 不在 PATH | 更新 App Installer;或按第 2 节加 PATH |
| 第一次用没反应,过一会儿才有 | 首次运行要建索引 | 正常,等 10–30 秒;或 winget source update |
| 搜不到某软件 | 仓库里确实没有 | 只能手工装,或者自己写 manifest 提交(进阶篇) |
| 搜到一堆重名 | 多源都有 | 加 -s winget 限定源 |
| 脚本里装错了软件 | 用了名称而不是 ID | 改用 --id + --exact |
| 装到一半 UAC 弹窗 | 需要提权 | 用管理员 PowerShell,或让脚本里已装的不重装 |
0x8A150011 | 安装包哈希与 manifest 不符 | 见进阶篇的哈希章节,不要随手加 --ignore-security-hash |
0x8A150014 | 没找到匹配的包 | ID 写错,或源里没有 |
0x8A150016 | 匹配到多个包 | 加 --id -e -s winget |
0x8A150010 | 没有适用于本机的安装器 | 架构不对,或该包不支持你的系统 |
| 装完提示要重启 | 正常 | 存一下工作,重启 |
| 卸载不干净 | manifest 缺卸载信息 | 走「设置 → 应用」手动卸 |
| 装完 PATH 里没有 | 安装器没改环境变量 | 新开一个终端窗口再试 |
winget list 里有但 uninstall 找不到 | 多源同名 | 补 -s 限定源 |
| 升完还是显示有新版本 | 预览版 / 索引过期 / 源不一致 | 见第 8 节 |
遇到看不懂的报错,第一反应应该是:
winget error 0x8A1500XX
下一步
- 进阶篇:WinGet 进阶 —— 源管理、
settings.json、版本锁定与迁移、代理、日志与错误码全集、批量与 CI,以及自己写 manifest 提交到 winget-pkgs。 - 官方文档:Use WinGet to install and manage applications
- 社区仓库:microsoft/winget-pkgs