param( [Parameter(Mandatory=$true)][string]$Out, [string]$Match = "DOSBox-X" ) Add-Type @" using System; using System.Runtime.InteropServices; public class W { [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr h, out RECT r); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr h); [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr h); [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr h, IntPtr hdc, uint flags); [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern int GetWindowText(IntPtr h, System.Text.StringBuilder s, int n); [DllImport("user32.dll")] public static extern bool EnumWindows(EnumProc cb, IntPtr p); public delegate bool EnumProc(IntPtr h, IntPtr p); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int L, T, R, B; } } "@ $found = @() $cb = [W+EnumProc]{ param($h, $p) if ([W]::IsWindowVisible($h)) { $sb = New-Object System.Text.StringBuilder 512 [void][W]::GetWindowText($h, $sb, 512) $t = $sb.ToString() if ($t -like "*$Match*") { $script:found += ,@($h, $t) } } return $true } [void][W]::EnumWindows($cb, [IntPtr]::Zero) if ($found.Count -eq 0) { Write-Output "NO-WINDOW"; exit 1 } Add-Type -AssemblyName System.Drawing function Test-Blank($bmp) { # sample a grid; blank/uniform => PrintWindow failed on this surface $seen = @{} for ($y = 10; $y -lt $bmp.Height - 10; $y += 23) { for ($x = 10; $x -lt $bmp.Width - 10; $x += 29) { $seen[$bmp.GetPixel($x, $y).ToArgb()] = $true if ($seen.Count -gt 6) { return $false } } } return $true } $i = 0 foreach ($f in $found) { $h = $f[0]; $title = $f[1] [void][W]::SetForegroundWindow($h) Start-Sleep -Milliseconds 600 $r = New-Object W+RECT [void][W]::GetWindowRect($h, [ref]$r) $w = $r.R - $r.L; $ht = $r.B - $r.T if ($w -le 0 -or $ht -le 0) { continue } # PRIMARY: PrintWindow(PW_RENDERFULLCONTENT) -- immune to occlusion $bmp = New-Object System.Drawing.Bitmap $w, $ht $g = [System.Drawing.Graphics]::FromImage($bmp) $hdc = $g.GetHdc() $ok = [W]::PrintWindow($h, $hdc, 2) $g.ReleaseHdc($hdc) $method = "PrintWindow" if (-not $ok -or (Test-Blank $bmp)) { # FALLBACK: screen copy (only valid if nothing is in front) $g.Dispose(); $bmp.Dispose() $bmp = New-Object System.Drawing.Bitmap $w, $ht $g = [System.Drawing.Graphics]::FromImage($bmp) $g.CopyFromScreen($r.L, $r.T, 0, 0, (New-Object System.Drawing.Size $w, $ht)) $method = "CopyFromScreen(FALLBACK -- occlusion-sensitive)" } $path = if ($found.Count -eq 1) { $Out } else { $Out -replace '\.png$', "_$i.png" } $bmp.Save($path, [System.Drawing.Imaging.ImageFormat]::Png) $g.Dispose(); $bmp.Dispose() Write-Output "SAVED $path ${w}x${ht} via $method [$title]" $i++ }