You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何判断PowerShell运行环境是ConHost还是Windows Terminal等终端,以避免窗口调整代码报错

如何判断PowerShell运行环境是ConHost还是Windows Terminal等终端,以避免窗口调整代码报错

我完全懂你那种每次打开PowerShell窗口光标都被任务栏挡住的烦躁!你的窗口调整脚本在ConHost里能完美解决问题,但到Windows Terminal就触发缓冲区大小报错,核心就是得先精准区分当前的终端环境,再决定要不要执行那些窗口调整逻辑。

下面给你几种靠谱的判断方式,以及修改后能兼容多终端的脚本方案:

一、判断终端环境的几种方法

1. 检查Windows Terminal专属环境变量

Windows Terminal会自动设置WT_SESSION环境变量,而ConHost、Cmder这类终端没有这个变量。直接用这个判断最简便:

# 判断是否在Windows Terminal中
$isWindowsTerminal = [bool]$env:WT_SESSION

2. 通过父进程判断(支持更多终端)

如果要覆盖Cmder、ConEmu这类其他终端,可以检查当前PowerShell进程的父进程名称:

$parentProcessId = (Get-CimInstance Win32_Process -Filter "ProcessId = $pid").ParentProcessId
$parentProcessName = (Get-Process -Id $parentProcessId -ErrorAction SilentlyContinue).Name

# 判断是否在Windows Terminal
$isWindowsTerminal = $parentProcessName -eq 'WindowsTerminal.exe'
# 判断是否在Cmder/ConEmu
$isCmder = $parentProcessName -match 'ConEmu|Cmder'
# 判断是否在原生ConHost
$isConHost = $parentProcessName -eq 'conhost.exe'

二、修改你的脚本,添加环境判断逻辑

把你的窗口调整代码加上条件判断,只在原生ConHost环境下执行,就能避免Windows Terminal里的报错了。修改后的完整脚本如下:

function Global:Set-ConsolePosition ($x, $y, $w, $h) {
    Add-Type -Name Window -Namespace Console -MemberDefinition '
    [DllImport("Kernel32.dll")]
    public static extern IntPtr GetConsoleWindow();
    [DllImport("user32.dll")]
    public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int W, int H); '

    $consoleHWND = [Console.Window]::GetConsoleWindow();
    $null = [Console.Window]::MoveWindow($consoleHWND, $x, $y, $w, $h);
}

function Global:Set-WindowState([int]$Type) {
    $Script:showWindowAsync = Add-Type -MemberDefinition @"
    [DllImport("user32.dll")]
    public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"@ -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru
    $null = $showWindowAsync::ShowWindowAsync((Get-Process -Id $pid).MainWindowHandle, $Type)
}

function Set-WindowClose() { Set-WindowState 0 }
function Set-WindowNormal() { Set-WindowState 1 }
function Set-WindowMin() { Set-WindowState 2 }
function Set-WindowMax() { Set-WindowState 3 }

function Global:Set-MaxWindowSize {
    # 只在原生ConHost环境下执行窗口调整
    $parentProcessId = (Get-CimInstance Win32_Process -Filter "ProcessId = $pid").ParentProcessId
    $parentProcessName = (Get-Process -Id $parentProcessId -ErrorAction SilentlyContinue).Name
    if ($parentProcessName -eq 'conhost.exe') {
        $MaxHeight = 32
        $MaxWidth = 120
        if ($MaxWidth -gt 120) { $MaxWidth = 120 }

        $MyBuffer = $Host.UI.RawUI.BufferSize
        $MyWindow = $Host.UI.RawUI.WindowSize
        $MyWindow.Height = $MaxHeight
        $MyWindow.Width = $MaxWidth
        $MyBuffer.Height = 9999
        $MyBuffer.Width = $MaxWidth

        $host.UI.RawUI.BufferSize = $MyBuffer
        $host.UI.RawUI.WindowSize = $MyWindow
    }
}

# 同样只在ConHost里执行窗口位置和状态调整
$parentProcessId = (Get-CimInstance Win32_Process -Filter "ProcessId = $pid").ParentProcessId
$parentProcessName = (Get-Process -Id $parentProcessId -ErrorAction SilentlyContinue).Name
if ($parentProcessName -eq 'conhost.exe') {
    Set-WindowNormal
    Set-ConsolePosition 75 20 500 400
}

为什么原来的代码在Windows Terminal报错?

Windows Terminal和ConHost的缓冲区大小限制不一样,你设置的9999行缓冲区高度超过了Windows Terminal允许的最大值,所以会触发"Cannot set the buffer size because the size specified is too large or too small"的错误。通过环境判断跳过这段逻辑就解决问题了。

备注:内容来源于stack exchange,提问作者YorSubs

火山引擎 最新活动