3

I use the below functions in my $profile to get around the incredibly annoying fact that Windows opens 80+% of new PowerShell windows with the cursor position below the taskbar so I have to move the window before using.

However, this generates an error in Windows Terminal:

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

So, how do I determine if I am currently running in ConHost or in Windows Terminal (or other terminals? maybe Cmder has a different host type?), so that I can create a condition in my $profile to not run this resizing option when I am in 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); '
    # 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

2 Answers 2

1

With props to Oisin Grehan in this GitHub comment, a simple but not always correct approach is to test for the presence of $env:WT_SESSION, which is only available in Windows Terminal sessions.

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

A more comprehensive solution, which requires PowerShell 7+, is suggested by Gerardo Grignoli:

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;
}
0

Just put a branching code in your profile that checks for host type, using If/Then statement.

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

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

If you are using many other shells that can load PS, then a switch statement can be used as well.

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

    'ConsoleHost' {
        # Do console customizations
    }

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

    Default {}
}
1
  • $Host.Name returns ConsoleHost for both Windows Terminal and conhost.exe (If you launch conhost and then start a PowerShell session within conhost.). 🙁 Commented Apr 12, 2023 at 9:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .