微软公司于北京时间 5 月 19 日 23 时开启了连续 48 小时的 Build 2020 开发者大会。由于疫情的影响,本届大会也从线下搬到了线上。如果说谷歌的 I/O 大会与国内消费者的关系不算很密切的话,那微软的 Build 大会对国内用户来说则是不亚于苹果 WWDC 的存在。每年的 Build 大会上都会宣布 Windows 操作系统、Office 等软件或服务的改进,足以令许多软粉翘首以盼,熬夜观看直播。
特别是自从微软 CEO 纳德拉宣布「Microsoft ❤️ Linux」的那一刻起,Windows 操作系统开始不断强化与 Linux 的兼容性,并且改善了许多曾经远远落后于 Linux 的体验。与此同时,逐步拥抱开源的微软更是屡屡亮出出人意料的崭新开源项目,今天的主角 Windows Package Manager 就是其中之一。
Windows Package Manager,以下简称 winget,是微软为 Windows 10 操作系统打造的软件管理命令行工具。引入 Powershell 后,在 Windows 10 操作系统上用命令行管理 APPX 软件包已经不再是难事;但对于存在了数十年的 Win32 应用程序来说,如何便捷地进行管理始终是一个难题。在 winget 出现以前,Scoop 和 Chocolatey 是这一问题的两大解决方案。关于这两个方案,我派过往的文章也有介绍:Scoop、Chocolatey。在总结部分我会比较 winget 和二者的异同,并给出选择建议。
如何体验 winget?
winget 支持的最低版本是 Windows 1709。也就是说,如果你当前仍然在使用早期 Windows 10 版本,或是 Windows Server 2016、Windows 8 及更早的版本,就无缘 winget 的更新了。Windows 10 用户可以打开设置 app,在「系统 > 关于」中查看版本号。
如下给出三种官方提供的直接安装方式:
- 如果你正在使用 Insider 版本,并且使用同一个微软账户登录了 Microsoft Store,你可以直接在 Microsoft Store 中更新「应用安装程序」,更新到最新版本即可使用 winget。
- 如果你运行的是正式版本,并且使用 Microsoft Store,你可以在这个 表单 中提交自己使用的微软账户,收到确认邮件后在 Microsoft Store 中直接更新,或者点击邮件中的链接跳转到 Microsoft Store 并更新。
- 如果你不希望使用 Microsoft Store,你可以在 发布页面 下载安装包并且双击安装。如果安装失败,请安装 Desktop Bridge VC++ v14 Redistributable Package 运行库后再次尝试。

安装完整后,打开 Powershell(命令提示符),输入 winget --info
并回车来查看安装信息。
winget 的定位和基本用法?
上文中已经提及,winget 目前主要是针对传统桌面 app 的管理工具,尽管已经支持 appx
软件包格式。对于 macOS 用户来说,很容易联想到 Homebrew Cask。从目前的版本来说,winget 的功能基本相当于 brew-cask,但稍有不足。不过,微软的野心显然不止于此,我会在后文中介绍一些已有规划但尚未实现的功能。
目前,winget 收录的 app 中虽然也有开源软件,但仍然以商业软件为主,这与 apt 这样的 Linux 包管理器收录标准截然不同,与 Homebrew Cask 则颇为接近(需要注意的是 Homebrew Core 依然遵循开放原则,不支持非自由软件)。目前来看,大部分 app 都由社区开发者提交,通常来说仓库管理员会保证来源的可靠性。但目前的开放做法较易引起对于安全性的担忧,尤其是在潜在用户规模庞大的情况下。
用最简单的、Linux 用户最熟悉的语言来表示,目前 winget 针对软件包的主要命令包括 show <package>
、install <package>
、search <key>
。尽管官方并未给出更详细的「使用姿势」,但是经过一系列测试我发现 winget 的机制可以说是十分「特色」,接下来我们就逐点分析。在分析过程中,我会引入 brew-cask 和 apt 两个比较对象,以帮助 Linux 和 macOS 用户更好地理解 winget 的一些独特机制。
winget 索引机制
winget 使用 HTTP 方式下载仓库索引,这从表面上看和 apt 相同。实际上,apt 中由于索引与软件仓库统一,apt 索引是直接对软件仓库中的包进行索引得到的。而 winget 在托管机制上和 brew-cask 更为相似,都是在 索引仓库 中存储每一个软件的配置文件,并且从第三方来源获取安装包。与后者不同的是,winget 并不直接使用 git,而是通过 CI 管道自动建立索引并且提交到服务器上。可能这就是枯燥吧,毕竟不管是 GitHub 还是 Azure 都是自家的(笑)。
由于使用了 HTTP 获取索引,winget 的索引更新方式为全量更新,在软件数量较多或者网络情况不佳(比如说目前国内网络访问就不太理想)的时候对体验的影响比较明显。可能是考虑到近期会有大量 app 提交,winget 当前为索引设置了很短的过期时间。这也就意味着,几乎每一次想要使用都得等待漫长的下载索引的过程。不过,随着 winget 的普及,我们有望看到微软为 winget 官方源配备全球 CDN,以及国内的各大高校、企业为它提供镜像源服务。

需要注意的是,winget 的索引似乎只针对 app 基本信息。这甚至意味着,在安装或者查看软件信息的时候还需要从服务器获取对应 app 的配置文件。这同时宣告目前 winget 在离线环境下的可用性几乎为零,希望后续可以改善。
和 brew-cask 相比,winget 对于多版本的支持是不折不扣的优势(但是目前不支持指定版本安装,优势无法体现);与同样支持多版本的 apt 相比,winget 由于没有受到发行版版本隔离的影响,版本号简洁了不少,在这一功能上可以说是超越了绝大多数软件包管理器。
不过,和 brew-cask 一样,winget 依赖第三方来源的特性意味着一旦第三方不再提供某一版本软件的下载,这一版本的配置将会失效,不知道财大气粗的微软是否会通过自动化的方式自动探测版本失效问题呢?如果开发者只提供最新版软件的下载,winget 又该怎么处理呢?在这方面,brew-cask 多年的经验积累或许可以为它提供一个较好的参考。
winget 的命名匹配
winget 的命名匹配机制与目前常见的绝大多数软件包管理器大相径庭。不同于简单的名称+配置方案,微软设计出包括名称、ID、别名、标签在内的命名体系。通过 winget show <package>
命令我们可以清楚地看到这一系列命名,以 Steam 为例:

在获取索引后,winget 根据输入的信息找到了名称为「Steam」的软件,它的 ID 则是「Valve.Steam」,这便是首行给出的信息。在接下来的行中,依次列出了版本、开发商、别名等相关信息。其中,从命名风格上看,别名 Moniker 和其他包管理器中的包名类似。这样看上去,是不是很友善、很全面?
此乃谎言!笔者刚上手的时候差点没被它的机制雷得外焦里嫩。在 show
指令的结果中,本应作为重要参考的标签竟然在详情页面没有提供,如此操作着实令人摸不着头脑;其次是缺失了描述,对于一些容易混淆的软件完全只能靠名字、开发商来辨别,对新用户很不友好。就拿许多读者都听说过的「swift」来说,这一名字同时对应了 Apple 公司主导开发的 Swift 编程语言和 OpenStack 套件中的 SWIFT 云存储组件;如果没有描述和标签辅助,混淆的概率恐怕不低。
奇怪的机制还在持续增加。如果你执行 winget show steam
,你就会发现它同时列出了 Git Extensions 这一项目。这个项目和 steam 有什么关系呢?原来是它的开发商代号「GitExtensionsTeam」中含有「sTeam」!先不说这个大部分包管理器中普遍存在的匹配问题,如果「别名」不能用来唯一地指定一个软件包,那么它存在的意义又是什么呢?

这一机制的副作用正如你们所见,就是对于部分软件包,即使是安装或者查看详情,为了消除二义性必须输入完整的 ID。哦对了,万一某一个包的 ID 恰好是另一个 ID 的子串怎么办?在发现这一盲点之后,我仔细搜寻,终于发现了这么一个无论如何都不能被安装的 app——似李,Microsoft.Edge(稳定版 Chromium Edge 浏览器)!
这个奇怪的机制还可能导致另一个问题:错误的匹配。要知道,winget 没有安装前确认步骤,在官方的路线图中也没有这一功能,这就意味着错误的软件包一旦进入了安装步骤就无法逆转了。而鉴于糟糕的匹配机制,诸如「njd」这样无意义的包名也会被匹配为「OpenJDK」,对于有需要的用户来说可控性实在太糟糕。或许微软应该考虑取消模糊匹配,改为只允许别名或 ID 匹配来得合适一些。
当然,标签和别名在搜索场景中还是有相当出色的表现的,而且对比其他包管理器来说算是独一档的优秀体验。如果对机制进行适当优化,至少不会比前辈们表现得更差。

winget 的安装体验
抛开糟糕的索引状况和匹配机制,winget 的安装体验出乎我意料地不错,尽管比起前辈还有不小的差距。首先我们来看看,当我输入 winget install Valve.Steam
的时候 winget 会做什么:
- 查找索引,如果不存在或过期则从服务器获取;
- 从索引匹配到包名称和版本号,然后从服务器获取其配置文件;
- 从配置文件中读取安装包地址;
- 从第三方来源下载安装包;
- 校验安装包 hash;
- 根据配置自动安装。
整个过程完成后的截图如下:

在以上两节中我们已经对前两个步骤有了比较直观的了解,读取步骤可以顾名思义,那么接下来就从第四步「下载」开始。winget 的下载器乍一看有进度条、有数值显示,实际上数值的单位之后 1MB。这也就意味着,尽管它默认精确到小数点后一位,那一位将始终为 0。
此外,我在使用的过程中无意间发现,整个 winget 的下载器竟然是单一且阻塞的。这也就意味着,你无法同时执行两个或多个 winget 下载任务。更奇怪的是,就连获取索引也会被软件下载进程阻塞。换句话说,在一个较长的安装流程中,整个 winget 基本陷入了不可用的状态(考虑到很短很短的缓存过期时间)。

winget 支持 hash 校验,而且支持多种哈希算法,这对于包管理器来说算是比较激进的设计。从目前的提交情况来看,所有的配置文件都提供了安装包的 hash,可以有效避免安装出错等情况,在这一点上 brew-cask 并非强制。由于暂时没有遇到 hash 错误,笔者暂时无法给出相应的体验情况。从我个人的体验上看,微软的哈希算法优化得很好,整个校验流程比较短,不过目前还没有办法预测在 CPU 性能较弱的 PC 上哈希算法的表现如何。
需要赞扬的是 winget 的所有软件都支持自动安装,这一点使其有资格成为合格的命令行包管理工具。不过,除了 Steam 等少数 app 之外,绝大多数 app 的安装过程中依然会显示安装器 UI,体验上稍微有些割裂。相比之下,brew-cask 的安装过程是完全无 GUI 的。

需要注意的是,由于目前 winget 默认将软件安装给所有用户,也即安装在 Program Files 或 Program Files (x86) 目录中,安装器启动时开启了 UAC(用户账户保护)的用户需要手动确认。如果不希望被 UAC 所干扰,可以使用管理员账户运行 Powershell 或命令提示符。使用管理员账户运行的 Windows Terminal 中,shell 默认以管理员身份创建。作为对比,brew-cask 安装中仅使用 pkg 安装器的 app 需要 sudo 提权,而且由于 sudo 提权有较长有效期,影响较 UAC 小上很多。
不过,Windows 10 的虚拟桌面功能给我们提供了一种最小打扰的方案:我们只需要在一个独立的虚拟桌面上使用管理员 PowerShell,就可以随时切换到自己原先的工作上而不被打扰。
「练习生」养成之路:winget 路线图
与前辈们相比,winget 还是个昨天才「出道」的小小「练习生」。诚然,它有着良好的家境(Windows 丰富的软件资源)与有钱的爹,但它也必须一步一个脚印地迈进,而不能「出道即巅峰」。根据 路线图,winget 将于一年后「正式毕业」,在这一年中它将学会包括但不限于以下几个与用户体验密切相关的技能:
- 安装来自 Microsoft Store 的软件(包括 UWP);
- 列出、更新、卸载当前已经安装的软件,甚至包括未通过 winget 安装的 Win32 软件;
- 支持同一个软件的不同语言、版本;
- 独立配置文件,从而允许云同步配置;
- 包括 Windows 旁白在内的无障碍支持;
- 可以选择安装给单个用户或全部用户;
- 自动提权,消灭 UAC 弹窗困扰;
- 支持批量安装,支持指定软件安装配置;
- 支持安装带有依赖的软件;
- 支持安装 PWA。
以上功能基本可以解决目前 winget 使用中的所有缺陷,并且一定程度上解决了其他包管理器使用中的痛点。一旦 winget 达到了完全体,它有望一跃而上,成为目前最先进、最强大的软件包管理工具。
总结:横向对比五大包管理器
由于 Windows Package Manager(winget)当前仅发布了首个测试版,许多功能还不够完善,在对比中我会将已经规划但尚未实现的功能用蓝色表示。


我认为,假以时日 Windows 的体验必将超过 Chocolatey,甚至赶超老前辈 Homebrew Cask。不过,在 winget 收录了足够多纯命令行工具和自由软件之前,Scoop 看上去依旧无可替代,并且可以成为 winget 的左膀右臂。
不过目前,winget 还完全不支持更新和卸载,仍然只是个纯粹(但是真的很纯粹)的安装器;建议绝大多数用户至少等待更新与卸载功能完善后再尝试使用。
展望:Windows 的大一统,从内外兼修开始
长期以来,Windows 在提供足够优质的图形界面体验、满足了一半用户需求的同时,由于命令行工具稀缺、自动化管理复杂、POSIX 兼容性差等问题饱受开发者尤其是跨平台开发者的诟病。发布 Linux 子系统、发布并开源 Windows Terminal……Build 大会见证着微软一步步拥抱 Linux 用户群与开源社区,也见证着 Windows 的命令行体验与跨平台兼容性大步迈进,时至今日业已非复吴下阿蒙。
Windows 的核心优势依旧是优秀的图形界面,但对开发者来说命令行的改进给了他们更宽广的可能。Windows Package Manager 发布的意义有哪些?除了进一步收录纯命令行工具外,「支持通过控制面板管理的 app」和「支持通过 Microsoft Store 安装的 app」让我看到了传统与现代,通过最原始、也是最纯粹的命令行,达成和谐的大一统的可能。这并非是空穴来风的猜测,毕竟在 Windows 可选功能管理中,类似的一幕已经上演。我们可以通过设置 app 和控制面板分别管理一部分可选功能,但是 PowerShell 却能让这些功能以完全一致的方式被高效地管理。
或许命令行就是连接 Win32 和 UWP 的一座,也是目前看来最可靠的,桥梁。而微软正号召整个开发者社群共同搭建这座属于 Windows 最终版本的梦幻之桥。
后记:winget 软件收录情况简报
截止北京时间 5 月 22 日中午 12 时,winget 软件仓库已经收录了数十个较为常用的 app,种类之丰富大大超过了我的预料。这些软件中既包括玩家们喜闻乐见的 Steam、Epic、Ubi 三大件,也有开发者们迫切需要的 Visual Studio、Vim、GitHub Desktop 和各类 Git 客户端。社区用户目前仍有上百个软件 PR 等待处理,基本可以肯定的是不需要担心收录情况。甚至,软件的丰富程度可能在短期内赶超 HomeBrew Cask。
各个大厂 app 的收录也十分迅速。截至目前,iTunes、WinRAR 等一系列国人耳熟能详(吐槽已久)的软件已经入库,另有格式工厂等正等待审核处理。不过,由于目前尚未有多语言支持,因此包括 WinRAR 在内的多语言分版本发行的 app 目前均只提供英文版本,不过后续应该会补足其他语言(对于国内用户来说,通过 winget 安装其他语言版本算是极好的绕开「广告定制版」的方式)。
主流通讯工具收录等也较为全面,微信、WhatsApp、Telegram 等各大 IM 软件以及 Zoom、腾讯会议(Voov)等在线会议软件均已收录。我通过翻阅 PR 列表发现,包括 QQ 音乐、腾讯视频在内的大部分腾讯系日常软件均有用户提交,这在国内企业中算是独一份的待遇,也侧面反映了腾讯系软件在 Windows 平台上的采用率和需求。
出乎我的意料,Windows Terminal、Ubuntu(WSL)等先前主要通过 Microsoft Store 分发的第一方工具也已经纳入支持范围。不过,鉴于 Microsoft Store 有着更完善的更新机制与 CDN 支持,目前仍不建议通过 winget 安装这些软件。
Chrome、Edge、FireFox、Opera 等主流浏览器也均有收录,从此旧版 Edge 的作用再也不是「新 Edge 下载器」或者「Chrome 下载器」(旧版 Edge:我不要面子的啊?)。不过,前文已经提及新 Edge 稳定版被匹配机制摆了一道,暂时无法安装,有需要的用户可以安装 Beta 版本,在稳定性和功能性上均有不错的保证。
另外,由于目前 winget 还未支持多架构安装器,绝大多数收录的 app 均只提供了 x64 版本。使用 32 位 Windows 或 Windows on ARM 的用户在目前会遭遇诸多不便,不妨等到多架构支持完善后再开始使用。winget 只支持从原始地址下载,这意味着国内用户下载部分无 CDN 或托管在 GitHub 的软件时可能进度缓慢甚至下载失败(由于粒度为 1MB,即使进度条毫无变化可能也在龟速下载,一旦彻底失去连接则会失败退出)。
以上就是目前 Windows Package Manager 第一方仓库收录情况的简评,感谢各位能看到这里。