Windows 默认终端程序设置(无交互设为 conhost / 指定 .bat 走 conhost)

结论

  1. 可以无交互直接设成 conhost —— 那两个设置界面的本质就是写两个注册表值,直接写注册表即可,效果完全一样,且不需要重启(新开的控制台窗口即生效)。
  2. “只让 .bat/.cmd 走 conhost、其他的走 Terminal”没有官方分类型开关(默认终端程序是全局、按用户的),但可以通过改 .bat/.cmd 的文件关联或脚本内自重启来绕过 Terminal,实现等价效果。

一、无交互把默认终端设成 conhost(等效“Windows 控制台主机”)

两个 HKCU\Console\%%Startup 下的值就是唯一的数据源(Terminal 设置 和 设置→系统→开发者选项→终端 两个入口写的都是它):

选项 DelegationConsole DelegationTerminal
让 Windows 决定 {00000000-0000-0000-0000-000000000000} 同左
Windows 控制台主机 (conhost) {B23D10C0-E52E-411E-9D5B-C09FDF709C7D} 同左(两个都填这个)
Windows 终端 (Terminal) {2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69} {E12CFF52-A866-4C77-9A90-F570A7AA2C6B}

PowerShell(推荐,单引号避免转义问题):

New-Item -Path 'HKCU:\Console\%%Startup' -Force | Out-Null
Set-ItemProperty -Path 'HKCU:\Console\%%Startup' -Name 'DelegationConsole' -Value '{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}' -Type String
Set-ItemProperty -Path 'HKCU:\Console\%%Startup' -Name 'DelegationTerminal' -Value '{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}' -Type String

或 .reg 文件(双击导入,一样无需交互)

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Console\%%Startup]
"DelegationConsole"="{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}"
"DelegationTerminal"="{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}"

或用 cmd 的 reg add(可完全替代 .reg 导入,已实测)

关键坑:%%Startup 键名里是**两个字面 %**,cmd 在不同场合对 % 的处理规则不同:

执行场合 写了什么 实际写入键名 结论
批处理文件 (.bat/.cmd) %%%%Startup %%Startup ✅ 需要 4 个 %
交互式 cmd / cmd /c "..." %%Startup %%Startup ✅ 只需 2 个 %

方案一:直接命令行 / cmd /c 执行(推荐)——把默认终端改回 conhost:

reg add "HKCU\Console\%%Startup" /v DelegationConsole  /t REG_SZ /d "{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}" /f
reg add "HKCU\Console\%%Startup" /v DelegationTerminal /t REG_SZ /d "{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}" /f

方案二:写成 .cmd/.bat 批处理文件——批处理里 %% 会被折叠成一个 %,键名要写 4 个 %:

@echo off
reg add "HKCU\Console\%%%%Startup" /v DelegationConsole /t REG_SZ /d "{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}" /f
reg add "HKCU\Console\%%%%Startup" /v DelegationTerminal /t REG_SZ /d "{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}" /f
  • /f 表示不提示直接覆盖(等价于 .reg 的覆盖行为)。
  • 需要改回 Windows Terminal 时,把 GUID 换成:
    • DelegationConsole → {2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69}
    • DelegationTerminal → {E12CFF52-A866-4C77-9A90-F570A7AA2C6B}
  • 想恢复系统默认(让 Windows 自行决定)就改成 {00000000-0000-0000-0000-000000000000}。
  • 已实测:reg add 写出的键名和 .reg/PowerShell 结果完全一致,普通用户权限即可写入 HKCU,无需提权。

注意:这是 HKCU(每用户) 的,没有对应的 HKLM 全机设置。若要为别的账户/提权上下文设置,需写那个身份自己的 HKCU。改回其他选项只需把两个值换成上表对应 GUID 即可。


二、只让 .bat/.cmd 走 conhost,其他照常走 Terminal

原理:默认终端程序(delegation)是全局的,但显式调用 conhost.exe 会绕过这个代理(这是官方 spec 里留的后门)。所以只要让 .bat/.cmd 的打开方式显式走一次 conhost 即可。

方案 A:改文件关联(只改当前用户,双击/ShellExecute 生效)

$assoc = 'HKCU:\Software\Classes'

foreach ($t in 'batfile','cmdfile') {
New-Item -Path "$assoc\$t\shell\open\command" -Force | Out-Null
Set-Item -Path "$assoc\$t\shell\open\command" -Value 'C:\Windows\System32\conhost.exe cmd.exe /c ""%1" %*"'
}

  • 原来默认值是 "%1" %*(直接执行,会被 Terminal 接管);改成显式 conhost.exe cmd.exe /c ... 后就不会被接管。
  • 若某些版本 conhost 需要参数分隔,可写成 conhost.exe -- cmd.exe /c ""%1" %*"。
  • 想还原:把该键的值改回 "%1" %* 即可。

方案 B:在脚本开头“检测到 Terminal 就重新用 conhost 启动自己”(不改系统设置)

@echo off
setlocal
set "id=%random%"
title %id%
tasklist /v /fo csv 2>nul | findstr /c:"%id%" | findstr /i /c:"cmd.exe" >nul
if errorlevel 1 (
start "" conhost "%~f0" %*
exit /b
)
rem ===== 下面才是真正的脚本内容 =====

原理:conhost 里窗口标题属于 cmd.exe,而 Windows Terminal 里属于 WindowsTerminal.exe,据此判断并重启自己到 conhost。属于社区 hack,可能有误判,但胜在零系统改动、可只针对个别脚本。


补充(可能影响实际体验)

  • 提权的控制台程序本来就会走 conhost:Terminal 的“默认终端接管”依赖 Packaged COM,提权上下文下不生效,所以以管理员身份运行的 .bat 本身就已经是 conhost 窗口(官方已知限制,issues #10276/#10682/#16666)。如果你要的正是“普通双击走 Terminal、提权走 conhost”,那其实系统默认就是这样。
  • 上述改关联/注册表均不需要管理员权限(写的是当前用户 HKCU),改完对新打开的窗口生效,无需重启。