param( [Parameter(Mandatory = $true)] [string]$Executable, [string]$OutputDirectory, [ValidateRange(0, 11)] [int]$PageIndex = -1 ) Add-Type -AssemblyName System.Drawing Add-Type @' using System; using System.Runtime.InteropServices; public static class NativeUiCapture { [StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left, Top, Right, Bottom; } [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hwnd, out Rect rect); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hwnd); [DllImport("user32.dll")] public static extern bool SetWindowPos( IntPtr hwnd, IntPtr after, int x, int y, int width, int height, uint flags); [DllImport("user32.dll")] public static extern bool SetCursorPos(int x, int y); [DllImport("user32.dll")] public static extern bool PrintWindow( IntPtr hwnd, IntPtr hdc, uint flags); [DllImport("user32.dll")] public static extern void mouse_event( uint flags, uint dx, uint dy, uint data, UIntPtr extraInfo); } '@ if ([string]::IsNullOrWhiteSpace($OutputDirectory)) { $OutputDirectory = Join-Path $PSScriptRoot '..\build\ui_screenshots' } $OutputDirectory = [System.IO.Path]::GetFullPath($OutputDirectory) New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null $processArguments = if ($PageIndex -ge 0) { @('--page-index', [string]$PageIndex) } else { @() } $process = Start-Process -FilePath $Executable -ArgumentList $processArguments -PassThru try { $deadline = [DateTime]::UtcNow.AddSeconds(20) do { Start-Sleep -Milliseconds 200 $process.Refresh() if ($process.HasExited) { throw "Application exited before creating its main window (exit code $($process.ExitCode))." } $windowValue = if ($null -eq $process.MainWindowHandle) { 0 } else { $process.MainWindowHandle.ToInt64() } } while ($windowValue -eq 0 -and [DateTime]::UtcNow -lt $deadline) if ($windowValue -eq 0) { throw "Application main window was not created." } [IntPtr]$handle = $process.MainWindowHandle [NativeUiCapture]::SetWindowPos($handle, [IntPtr]::Zero, 0, 0, 1440, 900, 0x0040) | Out-Null [NativeUiCapture]::SetForegroundWindow($handle) | Out-Null Start-Sleep -Seconds 3 $pageNames = @('system', 'arm', 'camera', 'agv', 'speaker', 'microphone', 'dexhand', 'biohead', 'hlc', 'test', 'quic', 'diagnostics') $pageIndexes = if ($PageIndex -ge 0) { @($PageIndex) } else { 0..($pageNames.Count - 1) } foreach ($index in $pageIndexes) { [NativeUiCapture]::SetForegroundWindow($handle) | Out-Null if ($PageIndex -lt 0) { $x = 100 $y = 164 + 46 * $index [NativeUiCapture]::SetCursorPos($x, $y) | Out-Null [NativeUiCapture]::mouse_event(0x0002, 0, 0, 0, [UIntPtr]::Zero) [NativeUiCapture]::mouse_event(0x0004, 0, 0, 0, [UIntPtr]::Zero) } Start-Sleep -Milliseconds 1500 $rect = New-Object NativeUiCapture+Rect [NativeUiCapture]::GetWindowRect($handle, [ref]$rect) | Out-Null $width = $rect.Right - $rect.Left $height = $rect.Bottom - $rect.Top $bitmap = New-Object System.Drawing.Bitmap($width, $height) $graphics = [System.Drawing.Graphics]::FromImage($bitmap) try { $deviceContext = $graphics.GetHdc() try { if (![NativeUiCapture]::PrintWindow($handle, $deviceContext, 2)) { throw "Failed to render the application window." } } finally { $graphics.ReleaseHdc($deviceContext) } $path = Join-Path $OutputDirectory ($pageNames[$index] + '.png') $bitmap.Save($path, [System.Drawing.Imaging.ImageFormat]::Png) } finally { $graphics.Dispose() $bitmap.Dispose() } } } finally { if (!$process.HasExited) { $process.CloseMainWindow() | Out-Null if (!$process.WaitForExit(5000)) { $process.Kill() } } }