Files
hrynco-kswitcher/tests/screenshot_process.ps1
T

69 lines
4.1 KiB
PowerShell

param([string]$Executable = "$PSScriptRoot\..\build\staged\KSwitcher.Screenshot.exe")
$ErrorActionPreference='Stop'
if (Get-Process KSwitcher.Screenshot -ErrorAction SilentlyContinue) { throw 'Close existing screenshot editors before this test.' }
Add-Type @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
public static class ScreenshotProcessTest {
public delegate bool EnumProc(IntPtr w, IntPtr p);
[DllImport("user32.dll")] static extern bool EnumWindows(EnumProc callback, IntPtr param);
[DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr w, out uint pid);
[DllImport("user32.dll", CharSet=CharSet.Unicode)] static extern int GetClassName(IntPtr w, StringBuilder name, int count);
[DllImport("user32.dll", CharSet=CharSet.Unicode)] static extern int GetWindowText(IntPtr w, StringBuilder name, int count);
[DllImport("user32.dll")] public static extern bool PostMessage(IntPtr w, uint msg, IntPtr wp, IntPtr lp);
public static IntPtr[] Windows(int process, string cls) {
var windows=new List<IntPtr>();
EnumWindows((w,p)=>{ uint pid; GetWindowThreadProcessId(w,out pid);
var name=new StringBuilder(256); GetClassName(w,name,256);
if(pid==process && name.ToString()==cls) windows.Add(w); return true;
},IntPtr.Zero); return windows.ToArray();
}
public static string Title(IntPtr w) { var s=new StringBuilder(256); GetWindowText(w,s,256); return s.ToString(); }
}
'@
function Wait-For([scriptblock]$Check,[string]$Message) {
for($attempt=0;$attempt -lt 100;$attempt++) { if (& $Check) { return }; Start-Sleep -Milliseconds 50 }
throw $Message
}
function Send($Window,$Message,$Wparam=0,$Lparam=0) {
[ScreenshotProcessTest]::PostMessage($Window,$Message,[IntPtr]$Wparam,[IntPtr]$Lparam) | Out-Null
}
function Capture-Windows { @([ScreenshotProcessTest]::Windows($script:process.Id,'KSwitcher.Capture')) }
function Select-Region($Window) {
Send $Window 0x201 1 ((40 -shl 16) -bor 40)
Send $Window 0x200 1 ((240 -shl 16) -bor 360)
Send $Window 0x202 0 ((240 -shl 16) -bor 360)
Wait-For { [ScreenshotProcessTest]::Title($Window) -match 'Screenshot #' } 'Selection did not become an editor.'
}
function Close-Editor($Window) {
Send $Window 0x10
Wait-For { @([ScreenshotProcessTest]::Windows($script:process.Id,'#32770')).Count -eq 1 } 'Missing close confirmation.'
$dialog=[ScreenshotProcessTest]::Windows($script:process.Id,'#32770')[0]
Send $dialog (0x400+102) 6 # TDM_CLICK_BUTTON / IDYES; no clipboard writes.
Wait-For { (Capture-Windows) -notcontains $Window } 'Editor did not close.'
}
$process=$null
try {
$process=Start-Process -FilePath $Executable -WindowStyle Hidden -PassThru
Wait-For { (Capture-Windows).Count -eq 1 } 'First selection did not open.'
$first=(Capture-Windows)[0]; Select-Region $first
$secondLaunch=Start-Process -FilePath $Executable -WindowStyle Hidden -PassThru
if (!$secondLaunch.WaitForExit(10000) -or $secondLaunch.ExitCode -ne 0) { throw 'Second launch did not hand off.' }
Wait-For { (Capture-Windows).Count -eq 2 } 'Second selection did not open in same process.'
$second=(Capture-Windows | Where-Object { $_ -ne $first })[0]; Select-Region $second
if ([ScreenshotProcessTest]::Title($first) -eq [ScreenshotProcessTest]::Title($second)) { throw 'Editor indices collide.' }
Close-Editor $first
if ($process.HasExited) { throw 'Process exited with an editor open.' }
Close-Editor $second
if (!$process.WaitForExit(5000) -or $process.ExitCode -ne 0) { throw 'Last editor did not exit process.' }
$process=Start-Process -FilePath $Executable -WindowStyle Hidden -PassThru
Wait-For { (Capture-Windows).Count -eq 1 } 'New process did not open selection.'
Send (Capture-Windows)[0] 0x100 27 # Esc cancels a selection only.
if (!$process.WaitForExit(5000) -or $process.ExitCode -ne 0) { throw 'Cancelling selection did not exit process.' }
'Passed screenshot process lifecycle checks'
} finally {
if ($process -and !$process.HasExited) { Stop-Process -Id $process.Id }
}