Windows Terminal设为默认终端时,如何用PowerShell隐藏控制台窗口?
背景
- 需求:在PowerShell脚本中隐藏控制台窗口
- 补充:开发一款常驻系统托盘、隐藏任务栏的截图脚本,该脚本依赖OneDrive存储截图,启动时需先完成OneDrive认证,因此初始阶段不能使用
-WindowStyle Hidden参数(需显示认证窗口),认证完成后需要隐藏终端窗口并显示系统托盘图标。
- 补充:开发一款常驻系统托盘、隐藏任务栏的截图脚本,该脚本依赖OneDrive存储截图,启动时需先完成OneDrive认证,因此初始阶段不能使用
- 环境适配:当Windows 11默认终端设为Windows Console Host时,可通过以下代码隐藏窗口:
$windowcode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);' $asyncwindow = Add-Type -MemberDefinition $windowcode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru $hwnd = (Get-Process -PID $pid).MainWindowHandle if ($hwnd -ne [System.IntPtr]::Zero) { $hidden = $asyncwindow::ShowWindowAsync($hwnd, 0) }
问题
当Windows 11默认终端设为Windows Terminal时,上述代码无法获取控制台窗口句柄。改用以下代码获取句柄后,ShowWindowAsync($hwnd, 0)仅会将Windows Terminal窗口最小化,而非完全隐藏:
Add-Type -Name ConsoleAPI -Namespace Win32Util -MemberDefinition '[DllImport("Kernel32.dll")] public static extern IntPtr GetConsoleWindow();' $hwnd = [Win32Util.ConsoleAPI]::GetConsoleWindow() $hidden = $asyncwindow::ShowWindowAsync($hwnd, 0)
解决方案
针对Windows Terminal作为默认终端的场景,可通过以下方法实现窗口隐藏:
方法1:使用同步ShowWindow函数替代ShowWindowAsync
ShowWindowAsync在Windows Terminal环境下行为受限,改用同步的ShowWindow函数,明确传入SW_HIDE(值为0)参数:
# 定义Win32 API函数 Add-Type -MemberDefinition @' [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow(); '@ -Name Win32WindowUtils -Namespace Win32 -PassThru # 获取控制台窗口句柄并隐藏 $hwnd = [Win32.Win32WindowUtils]::GetConsoleWindow() if ($hwnd -ne [System.IntPtr]::Zero) { [Win32.Win32WindowUtils]::ShowWindow($hwnd, 0) # 0对应SW_HIDE常量 }
方法2:通过窗口类名+标题匹配隐藏
如果方法1无效,可以通过Windows Terminal的专属类名结合窗口标题查找目标窗口:
Add-Type -MemberDefinition @' [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); '@ -Name Win32FindWindow -Namespace Win32 -PassThru # 获取当前PowerShell会话的窗口标题 $windowTitle = (Get-Host).UI.RawUI.WindowTitle # 匹配Windows Terminal的窗口类名与标题并隐藏 $hwnd = [Win32.Win32FindWindow]::FindWindow("CASCADIA_HOSTING_WINDOW_CLASS", $windowTitle) if ($hwnd -ne [System.IntPtr]::Zero) { [Win32.Win32FindWindow]::ShowWindow($hwnd, 0) }
方法3:认证完成后切换到无窗口进程
若需要彻底脱离终端环境,可在认证完成后通过VBScript启动无窗口的PowerShell进程,再退出当前终端:
- 编写VBScript脚本(例如命名为
HiddenLaunch.vbs):
Set objShell = CreateObject("WScript.Shell") objShell.Run "powershell.exe -WindowStyle Hidden -File ""你的脚本完整路径.ps1""", 0, False
- 在主脚本的认证完成逻辑后添加:
# 启动无窗口进程并退出当前终端 Start-Process "wscript.exe" -ArgumentList "HiddenLaunch.vbs" Exit
内容的提问来源于stack exchange,提问作者SATO Yusuke
相关产品推荐
相关产品推荐

