PowerShell,如果在 ConHost 中则运行代码,但如果在 Windows Terminal 中则不运行代码

PowerShell,如果在 ConHost 中则运行代码,但如果在 Windows Terminal 中则不运行代码

我使用下面的函数来$profile解决 Windows 使用光标位置打开 80% 以上的新 PowerShell 窗口这一令人恼火的事实以下任务栏所以我必须在使用之前移动窗口。

但是,这会在 Windows 终端中产生错误:

Exception setting "BufferSize": "Cannot set the buffer size because the size
specified is too large or too small. Actual value was 120,9999."

那么,我如何确定我当前是在 ConHost 中运行还是在 Windows 终端中运行(或其他终端?也许 Cmder 有不同的主机类型?),以便我可以创建一个条件,在$profile我使用 Windows 终端时不运行此调整大小选项?

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); '
    # Maybe do the Add-Type outside of the function as repeating it in a session can cause errors?
    $consoleHWND = [Console.Window]::GetConsoleWindow();
    $consoleHWND = [Console.Window]::MoveWindow($consoleHWND, $x, $y, $w, $h);
    # $consoleHWND = [Console.Window]::MoveWindow($consoleHWND,75,0,600,600);
    # $consoleHWND = [Console.Window]::MoveWindow($consoleHWND,-6,0,600,600);
}

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 {
    # This will open every new console in a reasonable position with cursor position visible
    # Added new restriction for ultrawide screens to cap the width to 175
    # https://gallery.technet.microsoft.com/scriptcenter/Set-the-PowerShell-Console-bd8b2ad1
    # https://stackoverflow.com/questions/5197278/how-to-go-fullscreen-in-powershell
    # "Also note: 'Mode 300' or 'Alt-Enter' to fullscreen a Conhost window`n"

    if ($Host.Name -match "console") {
        $MaxHeight = 32   # Setting to size relative to screen size: $host.UI.RawUI.MaxPhysicalWindowSize.Height - 5    # 1
        $MaxWidth = 120   # Setting to size relative to screen size: $host.UI.RawUI.MaxPhysicalWindowSize.Width - 15     # 15
        if ($MaxWidth -gt 120) { $MaxWidth = 120 }   # This is to handle ultra-wide monitors, was 175, but 100 is better
        $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.set_bufferSize($MyBuffer)
        # $host.UI.RawUI.set_windowSize($MyWindow)
        $host.UI.RawUI.BufferSize = $MyBuffer
        $host.UI.RawUI.WindowSize = $MyWindow
    }
}

Set-WindowNormal
Set-ConsolePosition 75 20 500 400

答案1

感谢奥辛·格雷汉此 GitHub 评论,一个简单但并不总是正确的方法是测试是否存在$env:WT_SESSION,这仅在 Windows 终端会话中可用。

if ($env:WT_SESSION) { 
    # yes, windows terminal
} else {
    # nope
}

A更全面的解决方案,需要 PowerShell 7+,建议使用杰拉尔多·格里尼奥利

function Get-ConsoleHostProcessId {
  
    # Save Original ConsoleHost title   
    $oldTitle=$host.ui.RawUI.WindowTitle; 
    # Set unique console title.
    $r=(New-Guid); 
    $host.ui.RawUI.WindowTitle = "$r"; 
    #Find console window by title, then find console PID.
    $result = (tasklist.exe /FO LIST /FI "WINDOWTITLE eq $r") | Select-String -Pattern  "PID:*" -Raw
    
    if ($null -ne $result) {
        $consolePid = [int]($result.SubString(5).Trim());
    } else {
        $consolePid = 0;
    }        
    # Restore original ConsoleHost title.
    $host.ui.RawUI.WindowTitle=$oldTitle;

    return [int]$consolePid;
}
  
function Test-IsWindowsTerminal {
    $consolePid = Get-ConsoleHostProcessId;
    if ($consolePid -gt 0) {
        return (Get-Process -PID (Get-ConsoleHostProcessId)).ProcessName -eq "WindowsTerminal";
    }
    return $false;
}

答案2

只需在您的配置文件中放置一个分支代码,使用 If/Then 语句检查主机类型。

If ($Host.Name -match 'ISE')
{
    # Do ISE customizations
}

If ($Host.Name -notmatch 'ISE')
{ 
    # Do console customizations
}

如果您正在使用许多其他可以加载 PS 的 shell,那么也可以使用 switch 语句。

switch ($host.Name)
{
    'Windows PowerShell ISE Host' {
        # Do ISE customizations
    }

    'ConsoleHost' {
        # Do console customizations
    }

    'Visual Studio Code Host' {
        # Do VSCode customizations
    }

    Default {}
}

相关内容