CmvrControlStation/scripts/capture_ui_pages.ps1

107 lines
4.1 KiB
PowerShell
Raw Permalink Normal View History

2026-09-18 16:22:20 +08:00
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()
}
}
}