绿色版 Chrome 设为 Win11 默认浏览器 —— 完整教程(网吧还原环境)

适用:Windows 11 23H2 (22631) / 绿色便携版 Chrome / C 盘每次开机还原、D 盘保留
效果:开机自动把 D 盘绿色 Chrome 设为默认浏览器,点 https 链接不弹任何”你要如何打开这个链接?”选择框
结论先行:三件事缺一不可——

  1. NoNewAppAlert=1 策略 → 治”弹窗”(实测 22631 上唯一有效的开关)
  2. 注册 ProgID ChromeHTML → 治”默认值指向的程序根本启动不了”
  3. SetUserFTA 写 UserChoice → 治”默认值本身”(带合法 Hash,不被系统重置)

Edge 开机抢占任务禁用属于可选保险,非必需(详见 §6)。


1. 原理:Windows 打开一个 https 链接时发生了什么

点链接
│
▼
读 HKCU\...\UrlAssociations\https\UserChoice ← ① 默认值是什么 ProgID? (带 Hash 校验)
│
▼
读 HKCU\Software\Classes\<ProgId>\shell\open\command ← ② 这个 ProgID 怎么启动?
│
▼
[首次打开时] windows.storage.dll!
CBindAndInvokeStaticVerb::ConfirmUserChoiceIfNewHandlersAvailable
│ 枚举当前"已注册的浏览器处理器", 发现 UserChoice 指向的是"新面孔"?
├── 是 → 弹"你要如何打开这个链接? 仅一次/始终" ← ③ 弹窗来源
└── 读到策略 NoNewAppAlert=1 → 直接跳过, 不弹 ← 唯一可靠关闭方式

网吧场景为什么必弹:C 盘还原后注册表被洗空,脚本每次开机重写 Chrome 的 ProgID/Capabilities/RegisteredApplications → 对 Windows 而言 Chrome 每次开机都是”新注册的处理器” → 每次开机首点必弹一次。
为什么 Hash 手写无效:UserChoice 带 keyed Hash(对 UserSid+ProgId 等做 MAC),手改会被 Windows 判非法并重置回 Edge。SetUserFTA 内置算法能算出合法 Hash。


2. 文件清单

文件 作用
D:\DevTools\Set-DefaultChrome.ps1 主脚本(下文 §4 全文)
D:\DevTools\SetUserFTA.exe Kolbicz 出品,算 Hash 写 UserChoice(kolbi.cz)
D:\DevTools\SetChrome.log 运行日志(D 盘不怕还原,出事查时间线)
D:\DevTools\All-Set.bat 开机自启入口,第 5 行左右调用主脚本

3. 执行顺序铁律

  1. NoNewAppAlert=1 必须最先写——策略到位后,后续一切”新处理器”判定都被豁免;
  2. ApplicationAssociationToasts 标记(若保留)必须先于 UserChoice,两者之间不插耗时操作;
  3. UserChoice 最后写——写早了没有意义(ProgID 还没注册);
  4. 全程 HKCU 为主,HKLM 策略需管理员(脚本经 All-Set.bat 提权跑时 HKLM 也能写上)。

4. 完整脚本(D:\DevTools\Set-DefaultChrome.ps1 最终版)

# ============================================================
# 把绿色 Chrome 设为默认浏览器 (http/https/.htm/.html/.shtml)
# Chrome: D:\AA-Program\Chrome\Application\chrome.exe
#
# 关键点:
# * ProgID 必须用 ChromeHTML (Chrome 只认这个, 用别的 Chrome 会一直提示"不再是默认")
# * URL 协议的 UserChoice 在 UrlAssociations\ 下, 不在 FileExts\ 下
# * 验证要直接读 UserChoice 注册表项, 不能用 SetUserFTA get (那个显示的是"有效关联", 会假成功)
# * 不弹"如何打开链接"的关键开关是策略 NoNewAppAlert=1 (第1步);
# 预写 ApplicationAssociationToasts 标记在 Win11 22631 实测拦不住弹窗, 仅作辅助保险
# * 无需重启; 全部写 HKCU, 以管理员运行时 HKLM 策略也一并写
# ============================================================

$ErrorActionPreference = "Stop"

$chrome = "D:\AA-Program\Chrome\Application\chrome.exe"
$progId = "ChromeHTML" # ← 不要改成 MyChromeHTML 之类
$appName = "Google Chrome"
$setUserFta = "D:\DevTools\SetUserFTA.exe"

# ---- 0. 前置检查 ----
if (-not (Test-Path $chrome)) { Write-Host "[X] chrome.exe 不存在: $chrome" -ForegroundColor Red; exit 1 }
if (-not (Test-Path $setUserFta)) { Write-Host "[X] SetUserFTA.exe 不存在: $setUserFta" -ForegroundColor Red; exit 1 }

# 日志: 每步时间落到 D 盘 (D 盘不被还原)
$log = "D:\DevTools\SetChrome.log"
function Write-Log($msg) {
"{0} {1}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"), $msg | Add-Content -Path $log -Encoding UTF8
}
Write-Log "=== Set-DefaultChrome 开始 ==="

# ---- 1. NoNewAppAlert=1 策略 —— 关弹窗的核心开关 (必须最先) ----
Write-Host "[1/5] 写入 NoNewAppAlert=1 策略 ..." -ForegroundColor Cyan
foreach ($root in @("HKCU:\Software\Policies\Microsoft\Windows\Explorer",
"HKLM:\Software\Policies\Microsoft\Windows\Explorer")) {
try {
New-Item -Path $root -Force | Out-Null
New-ItemProperty -Path $root -Name "NoNewAppAlert" -PropertyType DWord -Value 1 -Force | Out-Null
Write-Host "[OK] $root -> NoNewAppAlert=1" -ForegroundColor Green
} catch {
Write-Host "[!] $root 写入失败: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
Write-Log "[OK] NoNewAppAlert=1 已写"

# ---- 2. 预写"已提示过"标记 (辅助保险, 22631 实测无效但无害) ----
Write-Host "[2/5] 预写 ApplicationAssociationToasts 标记 ..." -ForegroundColor Cyan
$toasts = "HKCU:\Software\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts"
New-Item -Path $toasts -Force | Out-Null
foreach ($name in @("ChromeHTML_https","ChromeHTML_http","ChromeHTML_.htm","ChromeHTML_.html","ChromeHTML_.shtml")) {
New-ItemProperty -Path $toasts -Name $name -PropertyType DWord -Value 0 -Force | Out-Null
}
Write-Log "[OK] 提示标记 5 个已写"

# ---- 3. 注册 ProgID ChromeHTML (HKCU) ----
Write-Host "[3/5] 注册 ProgID: $progId ..." -ForegroundColor Cyan
$cls = "HKCU:\Software\Classes\$progId"
New-Item -Path $cls -Force | Out-Null
Set-ItemProperty -Path $cls -Name "(default)" -Value "Chrome HTML Document" -Force

$appKey = "$cls\Application"
New-Item -Path $appKey -Force | Out-Null
Set-ItemProperty -Path $appKey -Name "ApplicationName" -Value $appName -Force
Set-ItemProperty -Path $appKey -Name "ApplicationIcon" -Value "$chrome,0" -Force
Set-ItemProperty -Path $appKey -Name "ApplicationDescription" -Value "Access the Internet" -Force

$cmdKey = "$cls\shell\open\command"
New-Item -Path $cmdKey -Force | Out-Null
$cmdValue = "`"$chrome`" --single-argument %1"
Set-ItemProperty -Path $cmdKey -Name "(default)" -Value $cmdValue -Force

$iconKey = "$cls\DefaultIcon"
New-Item -Path $iconKey -Force | Out-Null
Set-ItemProperty -Path $iconKey -Name "(default)" -Value "$chrome,0" -Force
Write-Log "[OK] ProgID 已注册"

# ---- 4. 注册 StartMenuInternet 客户端 + Capabilities + RegisteredApplications ----
# 让 Chrome 出现在"设置>默认应用"列表, 且 Chrome 自检认出自己是默认 (去掉顶部黄条)
Write-Host "[4/5] 注册浏览器应用 ..." -ForegroundColor Cyan
$client = "HKCU:\Software\Clients\StartMenuInternet\$appName"
New-Item -Path $client -Force | Out-Null
Set-ItemProperty -Path $client -Name "(default)" -Value $appName -Force

New-Item -Path "$client\DefaultIcon" -Force | Out-Null
Set-ItemProperty -Path "$client\DefaultIcon" -Name "(default)" -Value "$chrome,0" -Force

New-Item -Path "$client\shell\open\command" -Force | Out-Null
Set-ItemProperty -Path "$client\shell\open\command" -Name "(default)" -Value "`"$chrome`"" -Force

$cap = "$client\Capabilities"
New-Item -Path $cap -Force | Out-Null
Set-ItemProperty -Path $cap -Name "ApplicationName" -Value $appName -Force
Set-ItemProperty -Path $cap -Name "ApplicationDescription" -Value "Access the Internet" -Force

$urlAssoc = "$cap\URLAssociations"
New-Item -Path $urlAssoc -Force | Out-Null
Set-ItemProperty -Path $urlAssoc -Name "http" -Value $progId -Force
Set-ItemProperty -Path $urlAssoc -Name "https" -Value $progId -Force

New-Item -Path "HKCU:\Software\RegisteredApplications" -Force | Out-Null
Set-ItemProperty -Path "HKCU:\Software\RegisteredApplications" -Name $appName `
-Value "Software\Clients\StartMenuInternet\$appName\Capabilities" -Force
Write-Log "[OK] 已注册为浏览器应用"

# ---- 5. 用 SetUserFTA 写 UserChoice ----
Write-Host "[5/5] 用 SetUserFTA 写 UserChoice ..." -ForegroundColor Cyan
foreach ($t in @("https", "http", ".htm", ".html", ".shtml")) { & $setUserFta $t $progId | Out-Null }
Write-Log "[OK] UserChoice 5 项已写"

# ---- 6. 验证: 直接读 UserChoice 注册表项 ----
function Check-Choice($label, $path) {
$k = Get-ItemProperty -Path "Registry::$path" -ErrorAction SilentlyContinue
if ($k -and $k.ProgId -eq $progId) {
Write-Host (" [OK] {0,-7} -> {1}" -f $label, $k.ProgId) -ForegroundColor Green
} else {
Write-Host (" [X] {0,-7} -> 期望 {1}" -f $label, $progId) -ForegroundColor Red
}
}
Check-Choice "https" "HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice"
Check-Choice "http" "HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice"
Check-Choice ".htm" "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.htm\UserChoice"
Check-Choice ".html" "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice"
Check-Choice ".shtml" "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.shtml\UserChoice"
Write-Log "=== Set-DefaultChrome 结束 ==="

5. 接入开机自启(All-Set.bat)

在 All-Set.bat 提权之后最先执行:

:: 把绿色 Chrome 设为默认 (必须每次开机跑, C 盘还原会洗掉注册表)
start "" /b powershell -NoProfile -ExecutionPolicy Bypass -File "D:\DevTools\Set-DefaultChrome.ps1"

要点:

  • -ExecutionPolicy Bypass 绕过策略限制;-NoProfile 提速;
  • 放在 All-Set.bat 前部,赶在用户点第一个链接之前跑完(实测 3~4 秒)。

6. 验证

# ① 默认值 (5 处都应是 ChromeHTML)
Get-ItemProperty "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice" | Select ProgId,Hash

# ② 弹窗开关 (HKCU 必有 1; HKLM 提权跑过才有)
Get-ItemProperty "HKCU:\Software\Policies\Microsoft\Windows\Explorer" NoNewAppAlert

# ③ 日志
Get-Content D:\DevTools\SetChrome.log -Tail 8

# ④ 实测: 点一个 https 链接, 应由绿色 Chrome 直接打开, 无任何弹窗

7. 踩坑录(本方案验证过程中证伪的假设)

曾经的怀疑 真相
UCPD.sys 会拦 SetUserFTA? 不会。UCPD 只拦”无 Hash 直改”,SetUserFTA 算出合法 Hash 写入畅通
UserChoice 的 Hash 会失效? SetUserFTA 算的 Hash 每次都有效;”重启后失效”其实是 C 盘还原把整个注册表洗了
预写”仅一次”标记能防弹窗? 22631 无效(标记全程在位仍弹),只对部分旧版本有效
用 SetUserFTA get 验证? 它显示的是”有效关联”,会假成功;必须直接读 UserChoice 项
ProgID 随便起名? Chrome 只认 ChromeHTML,改名会一直提示”不再是默认浏览器”
Edge 任务是弹窗元凶? 它确实想抢默认但全部 0x80070005 失败,与弹窗无关(弹窗源头是”新处理器”检查)

9. FAQ

Q:点链接还是弹”你要如何打开这个链接?”
A:查 NoNewAppAlert(HKCU、HKLM 都看),并确认脚本第 1 步在 UserChoice 之前执行、All-Set.bat 确实调用了脚本(看 SetChrome.log 当天有没有记录)。

Q:Chrome 能打开,但顶部黄条提示”不是默认浏览器”?
A:第 4 步(RegisteredApplications / Capabilities)没写成功,检查后重跑。

Q:链接还是被 Edge 打开?
A:第 5 步 SetUserFTA 没跑成(看日志),或第 6 步验证里 ProgId 不是 ChromeHTML。

Q:手动跑报”禁止运行脚本”?
A:powershell -NoProfile -ExecutionPolicy Bypass -File D:\DevTools\Set-DefaultChrome.ps1。

Q:网吧母盘换了新版 Windows 还灵吗?
A:核心机制(UserChoice+Hash、NoNewAppAlert)长期稳定;若弹窗复发,先按 §7 逐项验证,再看 SetChrome.log 时间线定位。