windows如何使用 winget!
windows如何使用 winget!
winget 作为 Windows 平台的现代化包管理器,为用户带来了诸多实际价值:
效率提升:通过命令行一键安装软件,无需手动访问网站、下载安装包、点击安装向导,大幅缩短软件部署时间。例如安装 Visual Studio Code 只需执行 winget install Microsoft.VisualStudioCode,整个过程自动完成。
批量管理:支持通过单条命令更新系统中所有已安装的软件(winget upgrade --all),彻底解决逐一检查更新的繁琐操作,特别适合需要维护多台设备的用户。
脚本化部署:开发者和 IT 管理员可以编写自动化脚本,快速配置新系统或统一部署企业应用,显著降低系统配置成本。配合 PowerShell 或批处理文件,可实现一键安装所需的全部开发工具链。
版本控制:winget 允许安装软件的特定版本,便于开发环境的精确管理。同时,所有安装的软件都经过 Microsoft 官方软件源验证,安全性有保障。
统一体验:为 Windows 用户提供了与 Linux(apt、yum)、macOS(Homebrew)类似的包管理体验,降低跨平台开发者的学习成本,提升工作流一致性。
系统要求与前置检查
在开始安装前,需要确认系统是否满足以下要求:
- 操作系统:Windows 10 版本 1809(内部版本号 17763)或更高版本、Windows 11 任意版本
- 系统架构:x64、x86 或 ARM64
- 必需组件:App Installer 应用(通常通过 Microsoft Store 安装)
检查是否已安装 winget 的方法非常简单。打开 PowerShell 或命令提示符,输入以下命令:
winget --version
如果返回版本号(如 v1.7.xxxx),说明系统已安装 winget。如果提示“不是内部或外部命令”,则需要按照下文方法进行安装。
安装方法
方法一:通过 Microsoft Store 安装(推荐)
这是最简单且最可靠的安装方式,适用于可以正常访问 Microsoft Store 的 Windows 10(1809+)和 Windows 11 系统。
具体步骤如下:
- 按
Win + S键打开搜索框,输入“Microsoft Store”并打开应用商店 - 在商店搜索栏中输入“App Installer”,如若搜索不到,请直接访问这个地址:https://apps.microsoft.com/detail/9NBLGGH4NNS1
- 点击“获取”或“安装”按钮,等待自动下载和安装完成
- 安装完成后,打开 PowerShell 或命令提示符,输入
winget --version验证安装成功
方法二:手动下载安装包(适用于无法访问 Microsoft Store 的情况)
部分企业版、教育版或 LTSC 版本的 Windows 系统可能禁用了 Microsoft Store,此时需要手动下载安装包。
第一步:下载主安装包
访问 winget 的 GitHub Releases 页面,在最新版本(Latest)的 Assets 部分找到并下载 Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle 文件。如果需要特定架构版本,也可下载对应的 .msix 文件。

第二步:下载依赖项
winget 运行需要以下两个依赖库:
- VCLibs(必需):从 Microsoft 官方链接下载 x64 版本,或根据系统架构选择 x86 / ARM64 版本
- UI.Xaml(Windows 10 必需):访问 NuGet Gallery,下载 Microsoft.UI.Xaml.2.8.x 包,将
.nupkg文件扩展名改为.zip并解压,在tools/AppX/x64/Release/目录下找到Microsoft.UI.Xaml.2.8.appx文件
第三步:安装依赖项和主程序
以管理员身份打开 PowerShell,依次执行以下命令(将路径替换为实际下载位置):
# 安装 VCLibs 依赖
Add-AppxPackage -Path "C:\Downloads\Microsoft.VCLibs.x64.14.00.Desktop.appx"
# 安装 UI.Xaml 依赖(Windows 10 系统需要)
Add-AppxPackage -Path "C:\Downloads\Microsoft.UI.Xaml.2.8.appx"
# 安装 winget 主程序
Add-AppxPackage -Path "C:\Downloads\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
安装完成后,重新打开终端并执行 winget --version 验证。
方法三:使用 PowerShell 自动化脚本(一键安装)
该方法通过脚本自动下载所有必需文件并完成安装,适合希望快速部署的用户。
以管理员身份打开 PowerShell,复制并执行以下脚本:
# 设置执行策略(如果需要)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# 自动化安装脚本
$progressPreference = 'silentlyContinue'
# 创建临时目录
$tempDir = New-Item -ItemType Directory -Path "$env:TEMP\winget-install" -Force
# 下载 VCLibs 依赖
Write-Host "正在下载 VCLibs..." -ForegroundColor Yellow
Invoke-WebRequest -Uri "https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx" -OutFile "$tempDir\VCLibs.appx"
# 下载 UI.Xaml 依赖
Write-Host "正在下载 UI.Xaml..." -ForegroundColor Yellow
Invoke-WebRequest -Uri "https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.6/Microsoft.UI.Xaml.2.8.x64.appx" -OutFile "$tempDir\UIXaml.appx"
# 获取并下载最新版 winget
Write-Host "正在获取最新版 winget..." -ForegroundColor Yellow
$releases = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
$msixUrl = ($releases.assets | Where-Object { $_.name -like "*.msixbundle" }).browser_download_url
Invoke-WebRequest -Uri $msixUrl -OutFile "$tempDir\winget.msixbundle"
# 安装依赖项
Write-Host "正在安装依赖项..." -ForegroundColor Yellow
Add-AppxPackage -Path "$tempDir\VCLibs.appx"
Add-AppxPackage -Path "$tempDir\UIXaml.appx"
# 安装 winget
Write-Host "正在安装 winget..." -ForegroundColor Yellow
Add-AppxPackage -Path "$tempDir\winget.msixbundle"
# 清理临时文件
Remove-Item -Path $tempDir -Recurse -Force
Write-Host "安装完成!请重新打开终端使用 winget。" -ForegroundColor Green
脚本执行完成后,关闭当前 PowerShell 窗口并打开新的终端窗口,即可使用 winget 命令。
方法四:LTSC 版本特殊处理
Windows 10 LTSC(长期服务渠道)版本默认不包含 Microsoft Store,需要先启用商店或完全手动安装。
方案 1:启用 Microsoft Store
以管理员身份运行 PowerShell,执行以下命令重新注册商店:
Get-AppxPackage -allusers Microsoft.WindowsStore | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}
或使用第三方脚本安装 Microsoft Store:
下面会给出
方案 2:完全手动安装(推荐)
直接按照“方法二”或“方法三”的步骤操作,无需依赖 Microsoft Store。
方法五:Chocolatey 用户快捷安装
如果系统已安装 Chocolatey 包管理器,可以通过以下命令快速安装 winget:
choco install winget-cli
常见问题排查
问题 1:提示“此应用无法在你的电脑上运行”
原因:系统版本过旧或架构不匹配。
解决方案:
- 执行
winver命令检查 Windows 版本,确保至少为 1809(内部版本号 17763) - 下载与系统架构(x64 / x86 / ARM64)匹配的安装包
- 通过 Windows 更新将系统升级到最新版本
问题 2:提示“无法安装,因为找不到依赖项”
原因:缺少 VCLibs 或 UI.Xaml 依赖库。
解决方案:严格按照“方法二”中的步骤 2 和步骤 3,先安装 VCLibs 和 UI.Xaml,再安装 winget 主程序。确保依赖项版本与系统架构一致。
问题 3:PowerShell 提示“Add-AppxPackage 不是可识别的 cmdlet”
原因:PowerShell 版本过旧或未以管理员权限运行。
解决方案:
- 右键点击 PowerShell,选择“以管理员身份运行”
- 更新 PowerShell 到最新版本:
winget install Microsoft.PowerShell(如 winget 已安装)或从 GitHub 下载最新版本
问题 4:Microsoft Store 无法访问
原因:企业环境网络限制或区域性访问问题。
解决方案:
- 使用“方法二”或“方法三”进行手动安装,完全不依赖 Microsoft Store
- 联系 IT 管理员开放 Microsoft Store 访问权限
- 配置网络代理或使用 VPN 服务
问题 5:安装后找不到 winget 命令
原因:环境变量未自动更新。
解决方案:
- 重新打开终端窗口(关闭旧窗口后再打开新窗口)
- 手动添加到系统 PATH:
$env:Path += ";C:\Users\$env:USERNAME\AppData\Local\Microsoft\WindowsApps" - 重启计算机以刷新环境变量
问题 6:提示“winget 需要开发者模式”
原因:某些早期版本的 winget 需要启用开发者模式。
解决方案:
- 打开“设置” > “更新和安全” > “开发者选项”
- 启用“开发人员模式”
- 重新运行 winget 安装命令
问题 7:LTSC 版本无法安装
原因:LTSC 版本默认不包含 Microsoft Store。
解决方案:参考“方法四”中的方案 1 启用 Microsoft Store,或使用方案 2 完全手动安装。
问题 8:安装包损坏或签名验证失败
原因:下载过程中文件损坏或来源不可信。
解决方案:
- 从 官方 GitHub 仓库重新下载安装包
- 使用
Get-FileHash -Path "文件路径" -Algorithm SHA256命令验证文件完整性 - 确保下载过程未使用不可靠的第三方镜像站
验证安装与基础使用
安装完成后,建议执行以下命令验证 winget 是否正常工作:
# 检查 winget 版本
winget --version
# 查看帮助信息
winget --help
# 测试搜索功能
winget search firefox
# 查看软件源配置
winget source list
预期输出应包含 msstore(Microsoft Store 源)和 winget(官方社区源)两个软件源。
常用命令示例
# 搜索软件
winget search <软件名称>
# 安装软件
winget install <软件名称>
# 列出已安装软件
winget list
# 更新指定软件
winget upgrade <软件名称>
# 更新所有软件
winget upgrade --all
# 卸载软件
winget uninstall <软件名称>
# 查看软件详细信息
winget show <软件名称>
更新与配置建议
自动更新
winget 会通过 Microsoft Store 自动更新。如需手动检查更新,可执行:
winget upgrade --id Microsoft.AppInstaller
或访问 Microsoft Store 的“下载和更新”页面手动获取更新。
启用实验性功能
winget 提供了一些实验性功能,可通过编辑配置文件启用。执行以下命令打开配置文件:
notepad %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\settings.json
示例配置:
{
"$schema": "https://aka.ms/winget-settings.schema.json",
"experimentalFeatures": {
"experimentalCmd": true,
"experimentalArg": true
},
"installBehavior": {
"preferences": {
"scope": "user"
}
}
}
获取方式
从 GitHub Release 页面:获取 winget
官方文档:Windows 包管理器文档
App Installer 下载:Microsoft Store 链接
winget 通过现代化的命令行界面,为 Windows 用户带来了高效、安全、可自动化的软件管理体验,无论是个人用户还是企业 IT 管理员,都能从中获得显著的生产力提升。
但实际上还是脚本更省事
火绒 360 会误报 ,执行前先关闭
先执行
install-winget.ps1
代码如下
===============开始
<# .SYNOPSIS 在受限网络 / 无 Microsoft Store 的 Windows 10 上安装 winget (Windows Package Manager) .DESCRIPTION 本机诊断结论(Windows 10 19045 / 22H2): 1. 系统里"有" App Installer 包,但版本只有 1.0.30251.0(约 2019 年); 2. winget 是 App Installer 1.11(2021 年)之后才引入的组件; 3. 所以 WindowsApps 目录下只有 python.exe 之类的 redirector,没有 winget.exe; 4. %LOCALAPPDATA%\Microsoft\WindowsApps 本来就在 PATH 里,不是环境变量问题; 5. 本机没有 Microsoft Store,所以"去商店更新"这条路也不通。 两个常见误区: - Add-AppxProvisionedPackage 是给系统镜像做"预置"的(需要 -LicensePath, 且微软并未为 winget 提供 License1.xml),必须用 Add-AppxPackage; - 逐个手搓依赖很容易漏。winget-cli 的 release 里官方提供了 DesktopAppInstaller_Dependencies.zip,本脚本直接用它,一次到位。 安装 App Installer 1.29 需要三组框架依赖(缺一个就报 0x80073CF3): - Microsoft.VCLibs.140.00 >= 14.0.33519.0
- Microsoft.VCLibs.140.00.UWPDesktop >= 14.0.33728.0
- Microsoft.WindowsAppRuntime.1.8 >= 8000.616.304.0
这些都在 Dependencies.zip 的 x64/ 目录里。
.PARAMETER Tag
winget-cli 的 release 标签,默认 v1.29.290(= https://aka.ms/getwinget 当前指向)。
.PARAMETER Mirror
GitHub 加速镜像前缀。默认 https://ghfast.top/
可选:https://gh-proxy.com/ https://ghproxy.net/
.PARAMETER DownloadDir
安装包存放目录,默认 %TEMP%\winget-install
已有且大小校验通过的文件会自动复用,不重复下载。
.PARAMETER Offline
跳过下载,只用 DownloadDir 中已有的文件。
.PARAMETER Cleanup
安装成功后删除下载的文件(约 315 MB)。
.EXAMPLE
powershell -ExecutionPolicy Bypass -File .\install-winget.ps1
.EXAMPLE
powershell -ExecutionPolicy Bypass -File .\install-winget.ps1 -Mirror "https://gh-proxy.com/"
#>
[CmdletBinding()]
param(
[string] $Tag = 'v1.29.290',
[string] $Mirror = 'https://ghfast.top/',
[string] $DownloadDir = "$env:TEMP\winget-install",
[switch] $Offline,
[switch] $Cleanup
)
$ErrorActionPreference = 'Stop'
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {}
# ======================= 配置区 =======================
$BundleFile = 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle'
$DepsFile = 'DesktopAppInstaller_Dependencies.zip'
$RelBase = "https://github.com/microsoft/winget-cli/releases/download/$Tag"
$BundleUrl = "$RelBase/$BundleFile"
$DepsUrl = "$RelBase/$DepsFile"
# 期望字节数(用于完整性校验;换 Tag 时若大小不符,脚本会提示但继续尝试)
$BundleSize = 216783252
$DepsSize = 97760717
$MirrorPool = @('https://ghfast.top/', 'https://gh-proxy.com/', 'https://ghproxy.net/')
# =====================================================
function Write-Step { param([string]$No, [string]$Text) Write-Host "`n[$No] $Text" -ForegroundColor Cyan }
function Write-Ok { param([string]$Text) Write-Host " OK $Text" -ForegroundColor Green }
function Write-Note { param([string]$Text) Write-Host " -- $Text" -ForegroundColor Gray }
function Write-Warn2{ param([string]$Text) Write-Host " !! $Text" -ForegroundColor Yellow }
function Get-Arch {
# ARM64 机器上如果跑的是 32 位 PowerShell,PROCESSOR_ARCHITECTURE 会是 x86,
# 必须优先看 PROCESSOR_ARCHITEW6432。
$a = $env:PROCESSOR_ARCHITEW6432
if (-not $a) { $a = $env:PROCESSOR_ARCHITECTURE }
switch ($a) {
'AMD64' { return 'x64' }
'ARM64' { return 'arm64' }
'x86' { return 'x86' }
default { return 'x64' }
}
}
function Test-DownloadedFile {
# 大小完全一致 -> 直接信任
# 大小不同 -> 换 Tag 或上游重新打包时会发生,只要还是个正经 ZIP 就接受
param([string]$Path, [long]$ExpectedSize)
if (-not (Test-Path $Path)) { return $false }
$len = (Get-Item $Path).Length
if ($ExpectedSize -gt 0 -and $len -eq $ExpectedSize) { return $true }
if ($len -lt 1MB) { return $false }
try {
$fs = [System.IO.File]::OpenRead($Path)
try { $b1 = $fs.ReadByte(); $b2 = $fs.ReadByte() } finally { $fs.Close() }
return ($b1 -eq 0x50 -and $b2 -eq 0x4B) # 'PK' -> ZIP/msixbundle
} catch { return $false }
}
function Get-RemoteFile {
param(
[string] $Url,
[string] $OutFile,
[long] $ExpectedSize,
[string[]] $Mirrors
)
if (Test-DownloadedFile -Path $OutFile -ExpectedSize $ExpectedSize) {
Write-Ok "复用已存在的 $(Split-Path $OutFile -Leaf)"
return $true
}
$curl = Join-Path $env:SystemRoot 'System32\curl.exe'
$useCurl = Test-Path $curl
$targets = @()
foreach ($m in $Mirrors) { if ($m) { $targets += ($m + $Url) } }
if ($Url -notlike 'https://github.com/*') { $targets += $Url }
if ($targets.Count -eq 0) { $targets = @($Url) }
$i = 0
foreach ($t in $targets) {
$i++
Write-Host " 尝试 $i/$($targets.Count) : $t" -ForegroundColor DarkGray
try {
if ($useCurl) {
& $curl -L --fail --connect-timeout 20 --retry 3 --retry-delay 3 --progress-bar -o $OutFile $t
if ($LASTEXITCODE -ne 0) { throw "curl 退出码 $LASTEXITCODE" }
} else {
$old = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri $t -OutFile $OutFile -UseBasicParsing -TimeoutSec 900
$ProgressPreference = $old
}
$len = (Get-Item $OutFile).Length
if (Test-DownloadedFile -Path $OutFile -ExpectedSize $ExpectedSize) {
if ($len -ne $ExpectedSize) {
Write-Warn2 "大小与预期不同(期望 $ExpectedSize / 实际 $len),但文件是有效压缩包,继续。"
}
Write-Ok "下载完成 $([math]::Round($len / 1MB, 1)) MB"
return $true
}
Write-Warn2 "下载内容无效(大小 $len),换下一个源"
}
catch {
Write-Warn2 "失败:$($_.Exception.Message)"
}
}
return $false
}
Write-Host "===================================================" -ForegroundColor White
Write-Host " winget 安装助手 (Windows Package Manager)" -ForegroundColor White
Write-Host "===================================================" -ForegroundColor White
# ---------------- 0. 环境检查 ----------------
Write-Step 0 '环境检查'
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
$os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
$osName = $os.Caption
$build = [int]$os.BuildNumber
$arch = Get-Arch
Write-Note "系统 : $osName (build $build)"
Write-Note "架构 : $arch"
Write-Note "用户 : $env:USERNAME"
Write-Note "管理员 : $isAdmin"
Write-Note "目标版本 : $Tag"
Write-Note "下载目录 : $DownloadDir"
if (-not $isAdmin) {
Write-Warn2 '当前不是管理员。为当前用户安装一般可行;若报权限错误,请用"管理员 PowerShell"重跑。'
}
if ($build -gt 0 -and $build -lt 17763) {
Write-Warn2 "winget 官方最低要求 Windows 10 1809 (build 17763),当前 build $build,很可能装不上。"
Write-Note '请改用 Windows 10 1809+ 或 Windows 11。'
}
if ($build -ge 22000) {
Write-Note '检测到 Windows 11 —— 正常情况下系统已自带 winget,本脚本会将其升级到最新版。'
}
# ---------------- 1. 现有状态 ----------------
Write-Step 1 '检查现有 App Installer'
$existing = Get-AppxPackage -Name Microsoft.DesktopAppInstaller -ErrorAction SilentlyContinue
if ($existing) {
Write-Note "当前包版本 : $($existing.Version)"
if ([version]$existing.Version -lt [version]'1.11.0.0') {
Write-Warn2 '版本低于 1.11,这正是 winget.exe 缺失的原因(该版本早于 winget 引入)。'
}
} else {
Write-Note '未检测到 App Installer 包,将全新安装。'
}
New-Item -ItemType Directory -Force -Path $DownloadDir | Out-Null
$bundlePath = Join-Path $DownloadDir $BundleFile
$depsZip = Join-Path $DownloadDir $DepsFile
$depsDir = Join-Path $DownloadDir 'deps'
# ---------------- 2. 下载 ----------------
Write-Step 2 '准备安装文件'
$mirrors = @($Mirror) + ($MirrorPool | Where-Object { $_ -ne $Mirror })
if ($Offline) {
Write-Note '-Offline 已指定,跳过下载。'
if (-not (Test-Path $bundlePath)) { throw "离线模式:找不到 $bundlePath" }
if (-not (Test-Path $depsZip)) { throw "离线模式:找不到 $depsZip" }
} else {
Write-Host " 依赖包 : $DepsFile (约 93 MB)" -ForegroundColor White
if (-not (Get-RemoteFile -Url $DepsUrl -OutFile $depsZip -ExpectedSize $DepsSize -Mirrors $mirrors)) {
throw '依赖包下载失败,请换 -Mirror 后重试。'
}
Write-Host " 主包 : $BundleFile (约 207 MB,请耐心等待)" -ForegroundColor White
if (-not (Get-RemoteFile -Url $BundleUrl -OutFile $bundlePath -ExpectedSize $BundleSize -Mirrors $mirrors)) {
throw 'App Installer 下载失败,请换 -Mirror 后重试。'
}
}
# ---------------- 3. 解压对应架构的依赖 ----------------
Write-Step 3 "解压 $arch 依赖"
if (Test-Path $depsDir) { Remove-Item -Path $depsDir -Recurse -Force -ErrorAction SilentlyContinue }
New-Item -ItemType Directory -Force -Path $depsDir | Out-Null
Add-Type -AssemblyName System.IO.Compression.FileSystem
$zip = [System.IO.Compression.ZipFile]::OpenRead($depsZip)
try {
$entries = $zip.Entries | Where-Object {
$_.FullName -like "$arch/*" -and -not $_.FullName.EndsWith('/')
}
if (-not $entries) {
$avail = ($zip.Entries | ForEach-Object { ($_.FullName -split '/')[0] } | Sort-Object -Unique) -join ', '
throw "在 $DepsFile 中找不到 $arch/ 目录(包内实际有:$avail),包结构可能已变化。"
}
foreach ($e in $entries) {
$dest = Join-Path $depsDir ([System.IO.Path]::GetFileName($e.FullName))
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($e, $dest, $true)
Write-Note "$([System.IO.Path]::GetFileName($e.FullName))"
}
} finally {
$zip.Dispose()
}
$depPaths = @(Get-ChildItem -Path $depsDir -Filter '*.appx' | ForEach-Object { $_.FullName })
if ($depPaths.Count -eq 0) { throw "解压后没有找到 .appx 依赖文件。" }
Write-Ok "共 $($depPaths.Count) 个 $arch 依赖"
# ---------------- 4. 安装 ----------------
Write-Step 4 '开始安装'
Get-ChildItem -Path $DownloadDir -Include '*.appx', '*.msixbundle' -Recurse -ErrorAction SilentlyContinue |
Unblock-File -ErrorAction SilentlyContinue
Write-Host " 安装主包 App Installer $Tag(连同 x64 依赖一起部署)..." -ForegroundColor White
Add-AppxPackage -Path $bundlePath -DependencyPath $depPaths -ForceApplicationShutdown -ErrorAction Stop
Write-Ok 'App Installer 安装完成'
# ---------------- 5. 验证 ----------------
Write-Step 5 '验证'
$wingetExe = Join-Path $env:LOCALAPPDATA 'Microsoft\WindowsApps\winget.exe'
$pkg = Get-AppxPackage -Name Microsoft.DesktopAppInstaller -ErrorAction SilentlyContinue
if ($pkg) { Write-Note "当前包版本 : $($pkg.Version)" }
if (Test-Path $wingetExe) {
Write-Ok "winget.exe 已就位:$wingetExe"
Write-Host ''
try { & $wingetExe --version } catch { Write-Warn2 "调用 winget 失败:$($_.Exception.Message)" }
Write-Host ''
Write-Host ' 完成!请【关闭并重新打开 PowerShell】,然后执行:' -ForegroundColor Yellow
Write-Host ' winget -v' -ForegroundColor Yellow
Write-Host ' winget search nodejs' -ForegroundColor Yellow
} else {
Write-Warn2 '未找到 winget.exe。可能原因:安装未完成 / 需要重新登录一次。'
Write-Note '可尝试:重启后再执行 winget -v;仍不行请把上面的完整输出发我。'
}
if ($Cleanup) {
Write-Step 6 '清理'
Remove-Item -Path $bundlePath, $depsZip -Force -ErrorAction SilentlyContinue
Remove-Item -Path $depsDir -Recurse -Force -ErrorAction SilentlyContinue
Write-Ok '已删除下载的安装包(释放约 315 MB)'
}
Write-Host ''
Write-Host '===================================================' -ForegroundColor White
===============结束
再执行
火绒 360 会误报 ,执行前先关闭
install-node.ps1
代码如下
===============开始
<# .SYNOPSIS 通过国内镜像安装 Node.js(不依赖 winget,跨 Windows 版本 / 跨 CPU 架构) .DESCRIPTION 为什么需要这个脚本:部分网络环境下 nodejs.org 直连不稳定、github.com 拉不动, 机器上也可能没有 winget。本脚本直接走 npmmirror 下载官方安装包。 【重要 - 杀软误报说明】 本脚本的行为是"联网下载官方安装包 -> 静默安装",这与"下载器木马"的启发式特征
高度重合,因此火绒/360 等国产杀软很可能报
HEUR:TrojanDownloader/PS.NetLoader.av
这是【误报】。处理办法见下方 .NOTES。
已处理的兼容性问题:
- x64 : 优先官方 .msi,失败自动退回 win-x64.zip
- arm64 : Node 官方【不提供 arm64 的 msi】,只能用 win-arm64.zip 解压安装
- x86 : Node 24 起已不再发布 32 位 Windows 包,脚本会提示改用 v22 线
- 未装 Node 的机器上探测版本不会再抛异常中断脚本
- 多镜像自动回退(npmmirror 两个入口 + 官方源兜底)
当前 LTS 线(2026-10):
v24.21.0 Krypton <- Active LTS,推荐(无 x86)
v22.23.3 Jod <- Maintenance LTS(有 x86)
v20.20.2 Iron <- Maintenance LTS(有 x86) 系统要求:Node 18+ 需要 Windows 10 1809 (build 17763) 或更高。 .NOTES 如果杀软拦截,三种处理方式(任选其一): 1) 把本脚本所在目录加入杀软的"信任区 / 排除目录",再执行; 2) 机器上已有 winget 时,直接用它,无需本脚本: winget install OpenJS.NodeJS.LTS 3) 手动下载安装:浏览器打开 https://registry.npmmirror.com/-/binary/node/ 进入对应版本目录,下载 node-vX.Y.Z-x64.msi 后双击安装。 .PARAMETER Version 要安装的版本,默认 v24.21.0。 .PARAMETER Method Auto(默认,按架构自动选择)/ Msi / Zip。 arm64 上强制 Zip;x86 上若该版本没有 msi 也会退到 Zip。 .PARAMETER DownloadDir 安装包存放目录,默认 %TEMP%\node-install .PARAMETER Cleanup 安装完成后删除安装包。 .EXAMPLE powershell -ExecutionPolicy Bypass -File .\install-node.ps1 .EXAMPLE # 32 位 Windows 请指定 v22 线 powershell -ExecutionPolicy Bypass -File .\install-node.ps1 -Version v22.23.3 #>
[CmdletBinding()]
param(
[string]
V
e
r
s
i
o
n
=
′
v
24.21.0
′
,
[
V
a
l
i
d
a
t
e
S
e
t
(
′
A
u
t
o
′
,
′
M
s
i
′
,
′
Z
i
p
′
)
]
[
s
t
r
i
n
g
]
Version=
′
v24.21.0
′
,[ValidateSet(
′
Auto
′
,
′
Msi
′
,
′
Zip
′
)][string]Method = 'Auto',
[string]
D
o
w
n
l
o
a
d
D
i
r
=
"
DownloadDir="env:TEMP\node-install",
[switch] $Cleanup
)
$ErrorActionPreference = 'Stop'
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {}
======================= 配置区 =======================
MirrorBases = @( 'https://registry.npmmirror.com/-/binary/node', # 阿里 npmmirror(主) 'https://npmmirror.com/mirrors/node', # 阿里 npmmirror(备用入口) 'https://nodejs.org/dist' # 官方源兜底 ) InstallDir = Join-Path $env:ProgramFiles 'nodejs'
=====================================================
function Write-Step { param([string]
N
o
,
[
s
t
r
i
n
g
]
No,[string]Text) Write-Host "`n[
N
o
]
No]Text" -ForegroundColor Cyan }
function Write-Ok { param([string]
T
e
x
t
)
W
r
i
t
e
−
H
o
s
t
"
O
K
Text)Write−Host"OKText" -ForegroundColor Green }
function Write-Note { param([string]
T
e
x
t
)
W
r
i
t
e
−
H
o
s
t
"
−
−
Text)Write−Host"−−Text" -ForegroundColor Gray }
function Write-Warn2{ param([string]
T
e
x
t
)
W
r
i
t
e
−
H
o
s
t
"
!
!
Text)Write−Host"!!Text" -ForegroundColor Yellow }
function Get-Arch {
# ARM64 机器上跑 32 位 PowerShell 时 PROCESSOR_ARCHITECTURE 会是 x86,需优先看 W6432
a
=
a=env:PROCESSOR_ARCHITEW6432
if (-not a) { a = env:PROCESSOR_ARCHITECTURE } switch (a) {
'AMD64' { return 'x64' }
'ARM64' { return 'arm64' }
'x86' { return 'x86' }
default { return 'x64' }
}
}
function Test-DownloadedFile {
# MSI 是 OLE 复合文档(头 D0 CF 11 E0),ZIP 是 PK。
# 只做"不是错误页"的最低限度校验:体积合理 + 魔数正确。
param([string]
P
a
t
h
,
[
s
t
r
i
n
g
]
Path,[string]Kind)
if (-not (Test-Path Path)) { return false }
l
e
n
=
(
G
e
t
−
I
t
e
m
len=(Get−ItemPath).Length
if (len -lt 1MB) { return false }
try {
f
s
=
[
S
y
s
t
e
m
.
I
O
.
F
i
l
e
]
:
:
O
p
e
n
R
e
a
d
(
fs=[System.IO.File]::OpenRead(Path)
try {
b
=
N
e
w
−
O
b
j
e
c
t
b
y
t
e
[
]
4
;
[
v
o
i
d
]
b=New−Objectbyte[]4;[void]fs.Read(b, 0, 4) } finally { fs.Close() }
if (Kind -eq 'Msi') { return (b[0] -eq 0xD0 -and
b
[
1
]
−
e
q
0
x
C
F
−
a
n
d
b[1]−eq0xCF−andb[2] -eq 0x11 -and b[3] -eq 0xE0) } return (b[0] -eq 0x50 -and b[1] -eq 0x4B) # 'PK' } catch { return false }
}
function Get-File {
param([string]
U
r
l
,
[
s
t
r
i
n
g
]
Url,[string]OutFile, [string]
K
i
n
d
)
i
f
(
T
e
s
t
−
D
o
w
n
l
o
a
d
e
d
F
i
l
e
−
P
a
t
h
Kind)if(Test−DownloadedFile−PathOutFile -Kind Kind) { Write-Ok "复用已存在的 (Split-Path
O
u
t
F
i
l
e
−
L
e
a
f
)
"
r
e
t
u
r
n
OutFile−Leaf)"returntrue
}
c
u
r
l
=
J
o
i
n
−
P
a
t
h
curl=Join−Pathenv:SystemRoot 'System32\curl.exe'
u
s
e
C
u
r
l
=
T
e
s
t
−
P
a
t
h
useCurl=Test−Pathcurl
Write-Host " 下载 Url" -ForegroundColor DarkGray try { if (useCurl) {
&
c
u
r
l
−
L
−
−
f
a
i
l
−
−
c
o
n
n
e
c
t
−
t
i
m
e
o
u
t
20
−
−
r
e
t
r
y
3
−
−
r
e
t
r
y
−
d
e
l
a
y
3
−
−
p
r
o
g
r
e
s
s
−
b
a
r
−
o
curl−L−−fail−−connect−timeout20−−retry3−−retry−delay3−−progress−bar−oOutFile
U
r
l
i
f
(
Urlif(LASTEXITCODE -ne 0) { return false } } else { old =
P
r
o
g
r
e
s
s
P
r
e
f
e
r
e
n
c
e
ProgressPreferenceProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri
U
r
l
−
O
u
t
F
i
l
e
Url−OutFileOutFile -UseBasicParsing -TimeoutSec 900
P
r
o
g
r
e
s
s
P
r
e
f
e
r
e
n
c
e
=
ProgressPreference=old
}
} catch { return $false }
if (Test-DownloadedFile -Path $OutFile -Kind $Kind) {
Write-Ok "下载完成 $([math]::Round((Get-Item $OutFile).Length / 1MB, 1)) MB"
return $true
}
return $false
}
Write-Host "===================================================" -ForegroundColor White
Write-Host " Node.js 安装助手(国内镜像,无需 winget)" -ForegroundColor White
Write-Host "===================================================" -ForegroundColor White
---------------- 0. 环境检查 ----------------
Write-Step 0 '环境检查'
i
s
A
d
m
i
n
=
(
[
S
e
c
u
r
i
t
y
.
P
r
i
n
c
i
p
a
l
.
W
i
n
d
o
w
s
P
r
i
n
c
i
p
a
l
]
[
S
e
c
u
r
i
t
y
.
P
r
i
n
c
i
p
a
l
.
W
i
n
d
o
w
s
I
d
e
n
t
i
t
y
]
:
:
G
e
t
C
u
r
r
e
n
t
(
)
)
.
I
s
I
n
R
o
l
e
(
[
S
e
c
u
r
i
t
y
.
P
r
i
n
c
i
p
a
l
.
W
i
n
d
o
w
s
B
u
i
l
t
I
n
R
o
l
e
]
:
:
A
d
m
i
n
i
s
t
r
a
t
o
r
)
isAdmin=([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
b
u
i
l
d
=
[
i
n
t
]
build=[int]os.BuildNumber
$arch = Get-Arch
探测已装 Node —— 必须容错:未安装时 & node 会抛 CommandNotFoundException,
在 ErrorActionPreference=Stop 下会直接中断整个脚本。
e
x
i
s
t
i
n
g
=
′
(
未安装
)
′
existing=
′
(未安装)
′
cmd = Get-Command node.exe -ErrorAction SilentlyContinue
if (cmd) { try { v = &
c
m
d
.
S
o
u
r
c
e
−
v
2
>
cmd.Source−v2>null | Select-Object -First 1
if (v) { existing = "
v
(
v(($cmd.Source))" }
} catch { }
}
Write-Note "系统 :
(
(os.Caption) (build
b
u
i
l
d
)
"
W
r
i
t
e
−
N
o
t
e
"
架构
:
build)"Write−Note"架构:arch"
Write-Note "用户 :
e
n
v
:
U
S
E
R
N
A
M
E
"
W
r
i
t
e
−
N
o
t
e
"
管理员
:
env:USERNAME"Write−Note"管理员:isAdmin"
Write-Note "目标版本 :
V
e
r
s
i
o
n
"
W
r
i
t
e
−
N
o
t
e
"
已装版本
:
Version"Write−Note"已装版本:existing"
if (
b
u
i
l
d
−
g
t
0
−
a
n
d
build−gt0−andbuild -lt 17763) {
Write-Warn2 "Node 18+ 需要 Windows 10 1809 (build 17763) 或更高,当前 build $build。"
}
---------------- 1. 决定安装包形态 ----------------
Write-Step 1 '选择安装包'
if (arch -eq 'arm64') { Write-Note 'arm64:Node 官方不提供 msi,只能用 win-arm64.zip 解压安装。' Method = 'Zip'
} elseif (
a
r
c
h
−
e
q
′
x
86
′
−
a
n
d
arch−eq
′
x86
′
−andMethod -eq 'Auto') {
Write-Note 'x86:优先尝试 msi(Node 24 起已不再发布 32 位包,可能需退回 v22 线)。'
Method = 'Msi' } elseif (Method -eq 'Auto') {
$Method = 'Msi'
}
候选文件名(按优先级)。MSI 命名不含 win-,ZIP 命名含 win-。
if (Method -eq 'Msi') { candidates = @(
[pscustomobject]@{ File = "node-
V
e
r
s
i
o
n
−
Version−arch.msi"; Kind = 'Msi' },
[pscustomobject]@{ File = "node-
V
e
r
s
i
o
n
−
w
i
n
−
Version−win−arch.zip"; Kind = 'Zip' }
)
} else {
candidates = @( [pscustomobject]@{ File = "node-Version-win-$arch.zip"; Kind = 'Zip' }
)
}
New-Item -ItemType Directory -Force -Path $DownloadDir | Out-Null
---------------- 2. 下载 ----------------
Write-Step 2 '下载安装包'
p
k
g
P
a
t
h
=
pkgPath=null
p
k
g
K
i
n
d
=
pkgKind=null
foreach (
c
i
n
cincandidates) {
foreach (
b
a
s
e
i
n
baseinMirrorBases) {
u
r
l
=
"
url="base/
V
e
r
s
i
o
n
/
Version/(
c
.
F
i
l
e
)
"
c.File)"out = Join-Path
D
o
w
n
l
o
a
d
D
i
r
DownloadDirc.File
if (Get-File -Url
u
r
l
−
O
u
t
F
i
l
e
url−OutFileout -Kind c.Kind) { pkgPath =
o
u
t
;
out;pkgKind = c.Kind break } Write-Warn2 "失败:url"
}
if ($pkgPath) { break }
}
if (-not pkgPath) { if (arch -eq 'x86') {
throw "x86 上找不到 Version 的安装包。Node 24 起已不再发布 32 位 Windows 版本,请改用:-Version v22.23.3" } throw "所有镜像均下载失败。请检查网络,或手动下载后放到 DownloadDir 再重跑。"
}
---------------- 3. 安装 ----------------
Write-Step 3 '开始安装'
if (pkgKind -eq 'Msi') { Write-Note "安装路径 : InstallDir"
Write-Note '同时会把 node/npm 加入系统 PATH'
m
s
i
L
o
g
=
J
o
i
n
−
P
a
t
h
msiLog=Join−PathDownloadDir 'node-install.log'
m
s
i
A
r
g
s
=
@
(
′
/
i
′
,
"
‘
"
msiArgs=@(
′
/i
′
,"‘"pkgPath"", '/qn', '/norestart', '/l*v', ""
m
s
i
L
o
g
‘
"
"
)
msiLog‘"")proc = Start-Process -FilePath 'msiexec.exe' -ArgumentList
m
s
i
A
r
g
s
−
W
a
i
t
−
P
a
s
s
T
h
r
u
i
f
(
msiArgs−Wait−PassThruif(proc.ExitCode -ne 0 -and proc.ExitCode -ne 3010) { throw "msiexec 退出码 (
p
r
o
c
.
E
x
i
t
C
o
d
e
)
,详见日志:
proc.ExitCode),详见日志:msiLog"
}
if (proc.ExitCode -eq 3010) { Write-Warn2 '安装成功,但建议重启系统以完成收尾。' } Write-Ok 'MSI 安装完成' } else { if (-not isAdmin) {
throw "解压安装需要写入 InstallDir,请用【管理员 PowerShell】重跑。" } if (Test-Path InstallDir) {
Write-Note "已存在
I
n
s
t
a
l
l
D
i
r
,将覆盖其中的文件。
"
R
e
m
o
v
e
−
I
t
e
m
−
P
a
t
h
InstallDir,将覆盖其中的文件。"Remove−Item−PathInstallDir -Recurse -Force -ErrorAction SilentlyContinue
}
New-Item -ItemType Directory -Force -Path
I
n
s
t
a
l
l
D
i
r
∣
O
u
t
−
N
u
l
l
InstallDir∣Out−Nulltmp = Join-Path
D
o
w
n
l
o
a
d
D
i
r
′
e
x
t
r
a
c
t
′
i
f
(
T
e
s
t
−
P
a
t
h
DownloadDir
′
extract
′
if(Test−Pathtmp) { Remove-Item -Path tmp -Recurse -Force -ErrorAction SilentlyContinue } Expand-Archive -Path pkgPath -DestinationPath $tmp -Force
# zip 内层还有一层目录(node-vX.Y.Z-win-arm64/),把里面的内容搬上来
$inner = Get-ChildItem -Path $tmp -Directory | Select-Object -First 1
if ($inner) { $src = $inner.FullName } else { $src = $tmp }
Copy-Item -Path (Join-Path $src '*') -Destination $InstallDir -Recurse -Force
Write-Ok "已解压到 $InstallDir"
# 写入系统 PATH(幂等)
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
$parts = @($machinePath -split ';' | Where-Object { $_ -and $_.Trim() })
if ($parts -notcontains $InstallDir) {
[Environment]::SetEnvironmentVariable('Path', (($parts + $InstallDir) -join ';'), 'Machine')
Write-Ok '已把 Node 目录加入系统 PATH(需新开终端生效)'
} else {
Write-Ok '系统 PATH 中已存在 Node 目录'
}
}
---------------- 4. 验证 ----------------
Write-Step 4 '验证'
n
o
d
e
E
x
e
=
J
o
i
n
−
P
a
t
h
nodeExe=Join−PathInstallDir 'node.exe'
if (Test-Path nodeExe) { Write-Ok "node.exe 已就位:nodeExe"
&
n
o
d
e
E
x
e
−
v
nodeExe−vnpmCmd = Join-Path
I
n
s
t
a
l
l
D
i
r
′
n
p
m
.
c
m
d
′
i
f
(
T
e
s
t
−
P
a
t
h
InstallDir
′
npm.cmd
′
if(Test−PathnpmCmd) { & npmCmd -v } Write-Host '' Write-Host ' 完成!请【关闭并重新打开 PowerShell】,然后执行:' -ForegroundColor Yellow Write-Host ' node -v ; npm -v' -ForegroundColor Yellow Write-Host ' 建议顺手换成国内 npm 源:' -ForegroundColor Yellow Write-Host ' npm config set registry https://registry.npmmirror.com' -ForegroundColor Yellow } else { Write-Warn2 "未在 InstallDir 找到 node.exe,请查看安装日志。"
}
if (Cleanup) { Write-Step 5 '清理' Get-ChildItem -Path DownloadDir -Force -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Write-Ok '已清理下载目录'
}
Write-Host ''
Write-Host '===================================================' -ForegroundColor White
===============结束
学习资料见知识星球。
以上就是今天要分享的技巧,你学会了吗?若有什么问题,欢迎在下方留言。
快来试试吧,小琥 my21ke007。获取 1000个免费 Excel模板福利!
更多技巧, www.excelbook.cn
欢迎 加入 零售创新 知识星球,知识星球主要以数据分析、报告分享、数据工具讨论为主;
1、价值上万元的专业的PPT报告模板。
2、专业案例分析和解读笔记。
3、实用的Excel、Word、PPT技巧。
4、VIP讨论群,共享资源。
5、优惠的会员商品。
6、一次付费只需129元,即可下载本站文章涉及的文件和软件。
