如何防止PowerShell控制台窗口标题被其他运行程序修改
编写PowerShell脚本通过$host.ui.rawui.windowtitle配置项设置控制台窗口标题后,启动同控制台下的交互式字符程序myapp.exe时,myapp.exe运行阶段会将控制台窗口标题替换为程序自身标题,仅在程序退出后才会恢复预设的标题,需要找到可行方法阻止myapp.exe运行时修改控制台窗口标题。
Windows控制台本身是挂载到该控制台的所有进程共享的系统资源,所有附着在同一个控制台的进程都有权限调用系统API修改控制台标题,系统没有提供原生的开关项直接禁止指定子进程修改标题,可根据使用场景选择以下方案:
轮询强制锁定标题(实现成本最低,推荐优先使用)
启动myapp.exe的同时在当前会话运行轻量循环,高频检查控制台标题,一旦发现标题被myapp.exe篡改就立刻改回预设值。只要检查间隔足够短,人眼完全感知不到毫秒级的标题闪烁,实际使用效果和直接拦截修改没有区别。
参考实现代码:# 定义你需要固定的自定义标题 $fixedTitle = "自定义控制台标题" $host.UI.RawUI.WindowTitle = $fixedTitle # 在当前控制台启动myapp,获取进程对象 $appProcess = Start-Process -FilePath ".\myapp.exe" -PassThru -NoNewWindow # 进程运行期间持续锁定标题 while (-not $appProcess.HasExited) { if ($host.UI.RawUI.WindowTitle -ne $fixedTitle) { $host.UI.RawUI.WindowTitle = $fixedTitle } # 检查间隔可自行调整,100ms间隔下基本看不到标题闪烁 Start-Sleep -Milliseconds 100 }API Hook拦截标题修改调用(无闪烁,实现成本较高)
myapp.exe修改控制台标题本质是调用了系统原生的SetConsoleTitleA/SetConsoleTitleW接口,你可以在启动程序前注入轻量Hook逻辑,拦截这两个接口的调用,当调用方为myapp.exe时直接返回成功结果,不实际执行标题修改操作。这个方案完全不会出现标题变动,但是需要借助Hook库实现,适合对使用体验要求极高的场景。为myapp分配独立控制台窗口(无侵入,适合不需要共用控制台的场景)
如果你不需要myapp.exe和当前PowerShell脚本共用同一个控制台交互,启动myapp.exe时去掉-NoNewWindow参数,系统会为myapp.exe创建独立的控制台窗口,myapp.exe只会修改自己所属窗口的标题,完全不会影响你原有PowerShell窗口的标题设置。
内容的提问来源于stack exchange,提问作者Eric van Loon

