Windows 开发环境每周维护 — MSYS2 · winget · 工具链一键更新
一个每周运行的 PowerShell 脚本,可更新 MSYS2 pacman、winget、Scoop、npm 全局包、rustup、cargo 二进制、pipx 和 Flutter。
Windows 开发环境始终是各种依赖的拼凑——IDE 来自 winget,gcc/make/git 来自 MSYS2,CLI 工具来自 scoop,全局包来自 npm/pip/cargo。每个工具的更新命令各不相同,一旦遗忘,最终就会出现类似 ld.exe: cannot find -lcrypt32 这样莫名其妙的 Tauri 构建失败。
我认为 Windows 环境维护问题的根本不在于各个工具的质量,而在于多工具更新步骤的分散性。以前开发者依靠记忆逐一更新;如今通过集成脚本一次覆盖所有工具,因为自动化的维护流程才能防止依赖版本漂移。
本文提供8 步集成 PowerShell 脚本来预防这种情况。每周运行一次——搞定。
TL;DR
MSYS2 pacman→winget→Scoop→npm -g→rustup→cargo install-update→pipx→flutter- MSYS2 是第一步:它是 Windows 上构建环境的操作系统。跳过它,原生构建就会像多米诺骨牌一样接连崩溃
- 每步如果工具未安装则自动跳过;一步失败不影响其余步骤
- 约 100 行 PowerShell,双击
update-system.bat即可运行
为什么 MSYS2 是第一步
Windows 的 winget 负责用户应用(Chrome、Slack……)和最终的开发工具产物。但真正编译代码的环境在 MSYS2 里——gcc、make、autotools、openssl 头文件、libsqlite、通过 pacman 管理的 zlib。
跳过一个月,你就会看到:
- Rust + Tauri 交叉编译因 OpenSSL 头文件版本不匹配而失败
- Python C 扩展构建(
pip install pillow等)因 freetype 版本偏差而失败 - 任何基于 MinGW 的构建因依赖库 ABI 不匹配而失败
这就是为什么 pacman -Syuu(双 u——含降级的同步)始终是第一步。
前置条件
- Windows 10 1709+ / 11(内置 winget)
- 完整的 8 步需要:预先安装 MSYS2、pipx、cargo-update、Flutter
- Scoop 可选——未安装时自动跳过
一次性准备
管理员 PowerShell:
# MSYS2(约 700MB)——构建环境的操作系统
winget install MSYS2.MSYS2
# pipx(Python 全局包管理器)
python -m pip install --user pipx
python -m pipx ensurepath
# cargo-update 扩展
cargo install cargo-update
# Flutter(约 1GB)
winget install Flutter.Flutter
# 如果 winget 没有:https://docs.flutter.dev/get-started/install/windows安装 MSYS2 后,打开 MSYS2 shell 运行一次 pacman -Syuu 同步基础包。
8 个更新步骤
| # | 步骤 | 命令 | 备注 |
|---|---|---|---|
| 1 | MSYS2 | pacman -Syuu | 构建环境的操作系统 — 第 1 步 |
| 2 | winget | winget upgrade --all | 系统包 |
| 3 | Scoop | scoop update * | 仅在已安装时执行 |
| 4 | npm 全局包 | npm update -g | 全局 npm 包 |
| 5 | Rust 工具链 | rustup update | stable channel |
| 6 | Cargo 二进制 | cargo install-update -a | 需要 cargo-update |
| 7 | pipx | pipx upgrade-all | Python 全局工具 |
| 8 | Flutter SDK | flutter upgrade | 当前 channel 的最新版 |
集成脚本
保存以下两个文件:
update-system.ps1(逻辑主体):
<#
.SYNOPSIS
批量系统工具更新 — Windows
.DESCRIPTION
一次性刷新构建环境 / 包管理器 / 语言工具链。
.NOTES
运行:update-system.bat(建议管理员权限)
目标:Windows 10/11
#>
$ErrorActionPreference = "Continue"
$script:Total = 8
$script:Step = 0
function Step-Header {
param([string]$Message)
$script:Step++
Write-Host ""
Write-Host ("[{0}/{1}] {2}" -f $script:Step, $script:Total, $Message) -ForegroundColor Cyan
}
function Has-Command {
param([string]$Cmd)
$null = Get-Command $Cmd -ErrorAction SilentlyContinue
return $?
}
function Write-OK { param([string]$m) Write-Host " OK $m" -ForegroundColor Green }
function Write-Skip { param([string]$m) Write-Host " SKIP $m" -ForegroundColor DarkGray }
function Write-Warn { param([string]$m) Write-Host " WARN $m" -ForegroundColor Yellow }
function Write-Fail { param([string]$m) Write-Host " FAIL $m" -ForegroundColor Red }
Write-Host "━━━ System update (Windows) ━━━" -ForegroundColor Cyan
# 1. MSYS2(最重要——构建环境的操作系统)
Step-Header "MSYS2 (pacman -Syuu) — critical"
$msys2Candidates = @(
"C:\msys64\usr\bin\bash.exe",
"D:\msys64\usr\bin\bash.exe",
"C:\tools\msys64\usr\bin\bash.exe"
)
$msys2Bash = $msys2Candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
if ($msys2Bash) {
Write-Host " → using: $msys2Bash" -ForegroundColor DarkGray
& $msys2Bash -lc "pacman -Syuu --noconfirm"
if ($LASTEXITCODE -eq 0) {
Write-OK "pacman -Syuu done (rerun once if core packages updated)"
} else {
Write-Fail "pacman -Syuu (after core updates, restart shell + rerun)"
}
} else {
Write-Skip "MSYS2 not installed (checked: C:\msys64, D:\msys64, C:\tools\msys64)"
}
# 2. winget
Step-Header "winget (system packages)"
if (Has-Command winget) {
winget upgrade --all --silent --accept-package-agreements --accept-source-agreements
if ($LASTEXITCODE -eq 0) { Write-OK "winget upgrade --all" }
else { Write-Fail "winget upgrade --all (some packages may need admin/interactive)" }
} else {
Write-Skip "winget not installed"
}
# 3. Scoop(可选)
Step-Header "Scoop (if installed)"
if (Has-Command scoop) {
scoop update
scoop update *
Write-OK "scoop update / update *"
} else {
Write-Skip "scoop not installed"
}
# 4. npm 全局包
Step-Header "npm globals"
if (Has-Command npm) {
npm update -g
if ($LASTEXITCODE -eq 0) { Write-OK "npm update -g" } else { Write-Fail "npm update -g" }
} else {
Write-Skip "npm not installed"
}
# 5. Rust 工具链
Step-Header "Rust toolchain (rustup)"
if (Has-Command rustup) {
rustup update
if ($LASTEXITCODE -eq 0) { Write-OK "rustup update" } else { Write-Fail "rustup update" }
} else {
Write-Skip "rustup not installed"
}
# 6. Cargo 二进制
Step-Header "Cargo binaries (cargo install-update -a)"
if (Has-Command cargo) {
cargo install-update --version 2>$null | Out-Null
if ($LASTEXITCODE -eq 0) {
cargo install-update -a
if ($LASTEXITCODE -eq 0) { Write-OK "cargo install-update -a" }
else { Write-Fail "cargo install-update -a" }
} else {
Write-Warn "cargo-update missing (install: cargo install cargo-update)"
}
} else {
Write-Skip "cargo not installed"
}
# 7. pipx
Step-Header "pipx (Python global tools)"
if (Has-Command pipx) {
pipx upgrade-all
if ($LASTEXITCODE -eq 0) { Write-OK "pipx upgrade-all" } else { Write-Fail "pipx upgrade-all" }
} else {
Write-Skip "pipx not installed"
}
# 8. Flutter SDK
Step-Header "Flutter SDK (flutter upgrade)"
if (Has-Command flutter) {
flutter upgrade
if ($LASTEXITCODE -eq 0) { Write-OK "flutter upgrade" } else { Write-Fail "flutter upgrade" }
} else {
Write-Skip "flutter not installed"
}
Write-Host ""
Write-Host "━━━ Done ━━━" -ForegroundColor Cyan
Write-Host "Checks: winget upgrade / npm outdated -g / pacman -Qu (MSYS2)" -ForegroundColor DarkGrayupdate-system.bat(双击入口):
@echo off
title System Update
echo ============================================
echo System Update (Windows)
echo MSYS2 + winget + npm + rustup + cargo + pipx
echo ============================================
echo.
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0update-system.ps1" %*
if %errorlevel% neq 0 (
echo.
echo [ERROR] Update failed. Check log above.
) else (
echo.
echo [DONE] System update complete.
)
pause将 .ps1 文件保存为 UTF-8 with BOM。 没有 BOM,Windows PowerShell 5.1 会乱码非 ASCII 输出。在 VS Code 中,点击右下角编码 → 「Save with Encoding」→ 「UTF-8 with BOM」。
示例输出
双击 update-system.bat(接受 UAC)。首次运行约 5–10 分钟(MSYS2 + winget),后续运行 1–3 分钟。
━━━ System update (Windows) ━━━
[1/8] MSYS2 (pacman -Syuu) — critical
→ using: C:\msys64\usr\bin\bash.exe
:: Synchronizing package databases...
:: Starting core system upgrade...
...
OK pacman -Syuu done (rerun once if core packages updated)
[2/8] winget (system packages)
Microsoft.VisualStudioCode 1.99.2 → 1.100.0
GitHub.cli 2.65.0 → 2.66.1
...
OK winget upgrade --all
[3/8] Scoop (if installed)
SKIP scoop not installed
[4/8] npm globals
OK npm update -g
...
━━━ Done ━━━
Checks: winget upgrade / npm outdated -g / pacman -Qu (MSYS2)
自动化——仅设置 Task Scheduler 提醒
不建议完全自动化。winget 偶尔会弹出 EULA 对话框,MSYS2 核心更新需要重启 shell,这会破坏无人值守的运行。设置提醒,而不是自动运行:
通过 PowerShell 配置 Task Scheduler:
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument '-NoProfile -Command "[System.Reflection.Assembly]::LoadWithPartialName(\"System.Windows.Forms\"); [System.Windows.Forms.MessageBox]::Show(\"Weekly update-system reminder\", \"Dev Maintenance\")"'
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Friday -At 10:00am
Register-ScheduledTask -TaskName "Dev Update Reminder" `
-Action $action -Trigger $trigger `
-Description "Weekly reminder to run update-system"每周五 10:00 弹出一个消息框,由你决定何时运行。
注意事项
- MSYS2 核心更新需要重启 shell 后再次运行:当 pacman 更新自身或核心库(libcurl、openssl)时,它会中断事务并要求重新运行。第一次完成后再运行一次
update-system.bat。 - 部分 winget 包需要交互式输入:大多数包用
--silent可静默安装,但新 EULA 会阻断流程。请手动安装这些包。 - Flutter 可能不在 winget 仓库中:如果
Flutter.Flutter未列出,从 docs.flutter.dev 下载 zip 并添加到 PATH。 - Scoop 是可选的:如果你只用 winget 或只用 scoop,另一步会干净地跳过。无冲突风险。
-Syuu中的第二个u:同步包括降级。MSYS2 有时会故意降级包;只用-Syu会积累冲突。
Mac 用户?
涵盖 brew + 语言工具链 + Flutter + CocoaPods 的同类指南 → Mac 开发环境每周维护。
总结
- 在 Windows 上,MSYS2 更新是优先级 #1
- 逐一更新工具 → 你会遗忘
- 一个集成脚本 → 随便忘,跑就行
- 只设置提醒,不要自动执行
- 每周一次可以防止构建中断、证书过期和 SDK 版本漂移