private/Position-ResizeWindow.ps1
function Position-ResizeWindow { [CmdletBinding()] Param( [Parameter(Mandatory=$True,Position=0)] #[ValidateRange(0, [int]::MaxValue)] [int]$ProcessId , [Parameter(Mandatory=$True,Position=1)] #[ValidateRange([int]::MinValue, [int]::MaxValue)] [int]$Left , [Parameter(Mandatory=$True,Position=2)] #[ValidateRange([int]::MinValue, [int]::MaxValue)] [int]$Top , [Parameter(Mandatory=$True,Position=3)] #[ValidateRange([int]::MinValue, [int]::MaxValue)] [int]$Width , [Parameter(Mandatory=$True,Position=4)] #[ValidateRange([int]::MinValue, [int]::MaxValue)] [int]$Height ) # NOTE: No longer using UIAutomation Module. # Get UIA object from process id, and manipulate its position and size #$w = Get-UiaWindow -ProcessId $processId #if ($w.CanMove -and $w.CanResize) { # $w.move($left, $top) | Out-Null # $w.Resize($width, $height) | Out-Null # $True #} # Using PInvoke: # http://www.pinvoke.net/default.aspx/user32.getwindowrect # http://www.pinvoke.net/default.aspx/user32.getclientrect # http://www.pinvoke.net/default.aspx/user32.movewindow # https://gist.github.com/coldnebo/1148334 $added = Add-Type ' using System; using System.Runtime.InteropServices; public class Win32 { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); } public struct RECT { public int Left; // x position of upper-left corner public int Top; // y position of upper-left corner public int Right; // x position of lower-right corner public int Bottom; // y position of lower-right corner } ' -PassThru if (!$added) { throw "Failed to load assemblies: System; System.Runtime.InteropServices" } # Keep trying to move the window until we are successful. "`t`tAttempting to move window......" | Write-Verbose $result = $null $loopCount = 0 $SleepMilliseconds = 10 while (!$result) { $loopCount++ # Get the process handle $process = Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Id -eq $ProcessId } | Select-Object -First 1 if ($process) { $handle = $process.MainWindowHandle # Debug "`t`Getting window handle......" | Write-Verbose "`t`tProcessId: $ProcessId handle: $handle" | Write-Verbose $window = New-Object RECT $client = New-Object RECT [Win32]::GetWindowRect($handle, [ref]$window) > $null [Win32]::GetClientRect($handle, [ref]$client) > $null "`t`twindow Left: $($window.Left), Top: $($window.Top), Right: $($window.Right), Bottom: $($window.Bottom)" | Write-Verbose "`t`tclient Left: $($client.Left), Top: $($client.Top), Right: $($client.Right), Bottom: $($client.Bottom)" | Write-Verbose # Draw it once far away, then draw it on its location. This makes the flicker less apparent $result = [Win32]::MoveWindow($handle, $Left, ($Top - 10000), $Width, $Height, $true) -and [Win32]::MoveWindow($handle, $Left, $Top, $Width, $Height, $true) if ($result) { # Successfully moved and sized window return $true } } Start-Sleep -Milliseconds $SleepMilliseconds # Stop looping if we failed too many times if ($loopCount -eq 100) { "We took too many loops ($loopCount) and $( $loopCount * $SleepMilliseconds )ms to position and resize a window." | Write-Verbose break } } if (!$result) { "Failed to get window handle! Loop count: $loopCount" | Write-Verbose } $false } |