PowerShell can call internal Windows API functions, and in this example, we’d like to show how you can change the show state of an application window. You’ll be able to maximize, minimize, hide, or show, for example.

The example uses PowerShell 5’s new enum capability to give the showstate numbers meaningful names. In older versions of PowerShell, simply remove the enum, and use the appropriate showstate numbers directly in the code.

The key learning point here is how to use Add-Type to take a C#-style signature of an API method and return a type that exposes this method to your PowerShell code:

#requires -Version 5
# this enum works in PowerShell 5 only
# in earlier versions, simply remove the enum,
# and use the numbers for the desired window state
# directly

Enum ShowStates
{
  Hide = 0
  Normal = 1
  Minimized = 2
  Maximized = 3
  ShowNoActivateRecentPosition = 4
  Show = 5
  MinimizeActivateNext = 6
  MinimizeNoActivate = 7
  ShowNoActivate = 8
  Restore = 9
  ShowDefault = 10
  ForceMinimize = 11
}


# the C#-style signature of an API function (see also www.pinvoke.net)
$code = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'

# add signature as new type to PowerShell (for this session)
$type = Add-Type -MemberDefinition $code -Name myAPI -PassThru

# access a process
# (in this example, we are accessing the current PowerShell host
#  with its process ID being present in $pid, but you can use
#  any process ID instead)
$process = Get-Process -Id $PID

# get the process window handle
$hwnd = $process.MainWindowHandle

# apply a new window size to the handle, i.e. hide the window completely
$type::ShowWindowAsync($hwnd, [ShowStates]::Hide)

Start-Sleep -Seconds 2
# restore the window handle again
$type::ShowWindowAsync($hwnd, [ShowStates]::Show)

Note how this example temporarily hides the PowerShell window for 2 seconds. You can now do the same to any running application window. Just use Get-Process to find the target process, and use its property “MainWindowHandle” to send the showstate change request.

Some applications manage multiple windows. In this case, you can only target the primary window or else would have to resort to additional API functions to first get a hold of the window handle of the child window.

Twitter This Tip! ReTweet this Tip!

Anonymous
  • That enum works fine in PowerShell 2 if you use Add-Type:

    Add-Type -TypeDefinition '
    public enum ShowStates
    {
        Hide = 0,
        Normal = 1,
        Minimized = 2,
        Maximized = 3,
        ShowNoActivateRecentPosition = 4,
        Show = 5,
        MinimizeActivateNext = 6,
        MinimizeNoActivate = 7,
        ShowNoActivate = 8,
        Restore = 9,
        ShowDefault = 10,
        ForceMinimize = 11,
    }
    '


    Windows PowerShell
    Copyright (C) 2009 Microsoft Corporation. All rights reserved.
    
    PS C:\Windows\system32> Add-Type -TypeDefinition '
    >> public enum ShowStates
    >> {
    >>     Hide = 0,
    >>     Normal = 1,
    >>     Minimized = 2,
    >>     Maximized = 3,
    >>     ShowNoActivateRecentPosition = 4,
    >>     Show = 5,
    >>     MinimizeActivateNext = 6,
    >>     MinimizeNoActivate = 7,
    >>     ShowNoActivate = 8,
    >>     Restore = 9,
    >>     ShowDefault = 10,
    >>     ForceMinimize = 11,
    >> }
    >> '
    >>
    PS C:\Windows\system32>
    PS C:\Windows\system32> [ShowStates]::Hide
    Hide
    PS C:\Windows\system32> $PSVersionTable
    
    Name                           Value
    ----                           -----
    CLRVersion                     2.0.50727.9035
    BuildVersion                   6.1.7600.16385
    PSVersion                      2.0
    WSManStackVersion              2.0
    PSCompatibleVersions           {1.0, 2.0}
    SerializationVersion           1.1.0.1
    PSRemotingProtocolVersion      2.1
    
    
    PS C:\Windows\system32>

  • And get windows to front

    $code2 = '[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr WindowHandle);'

    $type2 = Add-Type -MemberDefinition $code2 -Name myAPI2 -PassThru

    Start-Sleep -Seconds 2

    $type2::SetForegroundWindow($hwnd)