-1

I have these handy functions to flip console sizes from the command line. The only problem is that they don't work if the console window is in the maximized state. Is there a way to toggle Maximize / Restore for the console window from the PowerShell prompt?

function Global:Set-ConsolePosition ($x, $y, $w, $h) {
    # Keep this function in ProfileExtensions as used during updates
    # Note: the DLL code below must not be indented from the left-side or will break
    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); '
    # 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);
}

# Does not "maximize" but sets the window to the maximum extent allowed by the screensize.
function Global:Set-MaxWindowSize {
    # Keep this function in ProfileExtensions as used during updates
    # This will open every new console pinned to top of screen and large size
    # 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' and 'Alt-Enter' to fullscreen the console`n"

    if ($Host.Name -match "console") {
        $MaxHeight = $host.UI.RawUI.MaxPhysicalWindowSize.Height - 5    # 1
        $MaxWidth = $host.UI.RawUI.MaxPhysicalWindowSize.Width - 15     # 15
        if ($MaxWidth -gt 175) { $MaxWidth = 175}
        $MyBuffer = $Host.UI.RawUI.BufferSize
        $MyWindow = $Host.UI.RawUI.WindowSize
        $MyWindow.Height = ($MaxHeight)
        $MyWindow.Width = ($MaxWidth-2)
        $MyBuffer.Height = (9999)
        $MyBuffer.Width = ($MaxWidth-2)
        # $host.UI.RawUI.set_bufferSize($MyBuffer)
        # $host.UI.RawUI.set_windowSize($MyWindow)
        $host.UI.RawUI.BufferSize = $MyBuffer
        $host.UI.RawUI.WindowSize = $MyWindow
    }
}

# Set the window to be half-screen, left side
function lll {
    Add-Type -AssemblyName System.Windows.Forms
    $Screen = [System.Windows.Forms.Screen]::PrimaryScreen
    $width = $Screen.WorkingArea.Width   # .WorkingArea ignores the taskbar, .Bounds is whole screen
    $height = $Screen.WorkingArea.Height
    $w = $width/2 + 13
    $h = $height + 8
    $x = -7
    $y = 0
    Set-ConsolePosition $x $y $w $h

    $MyBuffer = $Host.UI.RawUI.BufferSize
    $MyWindow = $Host.UI.RawUI.WindowSize
    $MyBuffer.Height = 9999
    "`nWindowSize $($MyWindow.Width)x$($MyWindow.Height) (Buffer $($MyBuffer.Width)x$($MyBuffer.Height))"
    "Position : Left:$x Top:$y Width:$w Height:$h`n"
}

# Set the window to be half-screen, right side
function rrr {
    Add-Type -AssemblyName System.Windows.Forms
    $Screen = [System.Windows.Forms.Screen]::PrimaryScreen
    $width = $Screen.WorkingArea.Width   # .WorkingArea ignores the taskbar, .Bounds is whole screen
    $height = $Screen.WorkingArea.Height
    $w = $width/2 + 13
    $h = $height + 8
    $x = $w - 20
    $y = 0
    Set-ConsolePosition $x $y $w $h

    $MyBuffer = $Host.UI.RawUI.BufferSize
    $MyWindow = $Host.UI.RawUI.WindowSize
    $MyBuffer.Height = 9999
    "`nWindowSize $($MyWindow.Width)x$($MyWindow.Height) (Buffer $($MyBuffer.Width)x$($MyBuffer.Height))"
    "Position : Left:$x Top:$y Width:$w Height:$h`n"
}

# Set the window to be full-size
function fff {
    Set-ConsolePosition -7 0 600 600
    if ($Host.Name -match "console") {
        $MaxHeight = $host.UI.RawUI.MaxPhysicalWindowSize.Height - 1
        $MaxWidth = $host.UI.RawUI.MaxPhysicalWindowSize.Width
        $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
        "`nWindowSize $($MyWindow.Width)x$($MyWindow.Height) (Buffer $($MyBuffer.Width)x$($MyBuffer.Height))`n"
    }
}

# Only run this the first time that Profile Extensions are run in this session (i.e. so that ". pect" will not reactivate this)
if ($null -eq $ProfileExtensionsFirstRun) {
    Set-ConsolePosition 75 0 600 600
    Set-MaxWindowSize
}
YorSubs
  • 3,194
  • 7
  • 37
  • 60
  • 3
    What is `Set-ConsolePosition`? Please add its definition. Also a short comment above each function, that tells what it is supposed to do, would be helpful. – zett42 Apr 24 '22 at 21:48
  • 2
    Basically what you need to do is P/Invoke `ShowWindow(GetConsoleWindow(), SW_RESTORE)`. – zett42 Apr 24 '22 at 21:52
  • 1
    Sorry, @zett42, you are right, I have added in the essential missing information. – YorSubs Apr 25 '22 at 05:41

1 Answers1

1

I found a script online and tweaked it to set the current window to normal - put this near the top of your script

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

Now calling Set-WindowNormal should set the self window to normal. Put this where you want to normalize your window. (before the necessary function call most likely)

I can't seem to find a better answer really.

In the code above. There are several ways to show a window. https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow explains them. 1 is normal. 2 is minimized etc...

This is the answer I was able to find. Apparently this is a tricky question.

Robert Cotterman
  • 2,213
  • 2
  • 10
  • 19
  • 1
    This is amazing, I've been after this for a long time. So now, I will simply always do a `Set-WindowNormal` as the first line in my `lll`, `rrr`, `fff` to ensure that the console window is in a non-maxmised state before I resize. From testing so far, this seems perfect thanks. – YorSubs Apr 25 '22 at 05:45
  • 1
    One of the reasons that I want these functions, is that consoles on Windows are quite "badly behaved" in my experience (most of the time when I open a new console the bottom of the window is off the bottom of the screen, so I cannot see the cursor and have to move things around). In a maximised state, my functions don't work, so now I can just do: `Set-ConsolePosition 75 0 600 600` to position things, then `Set-WindowNormal` in case it is maximised, then `Set-MaxWindowSize` to ensure that the screen is in a useful position. – YorSubs Apr 25 '22 at 05:52
  • I'm glad it worked. Keep up the scripting! – Robert Cotterman Apr 26 '22 at 04:03