]> vilimpoc.org git repositories - dotfiles/commitdiff
dotfiles: a Windows 7 test-target setup script
authorMax Vilimpoc <max@vilimpoc.org>
Wed, 26 Aug 2026 12:40:08 +0000 (14:40 +0200)
committerMax Vilimpoc <max@vilimpoc.org>
Mon, 31 Aug 2026 15:27:35 +0000 (17:27 +0200)
Provisioning a Windows 7 VM so it can be driven from the host by VBoxManage
guestcontrol takes a handful of settings that are easy to forget and easy to
get wrong, and every one of them here was learned by hitting it:

- Windows Error Reporting's dialog blocks a guestcontrol call until the host's
  timeout. A harness that scores a timeout as a failure then invents bugs that
  do not exist, so DontShowUI is not a nicety.
- The host watches the guest with controlvm screenshotpng, so a screen saver or
  a blanked monitor makes every screenshot useless.
- Bulk transfer over the VirtualBox shared folder is far faster than a copyto
  per file, but the mapping is per-user and does not survive into a new
  interactive session.

The readiness report is the other half of the point. A test run against a box
with no printer, or no audio capture device, reads as "the software under test
refused" when the truth is "this VM never had one". It reports DWM composition
for the same reason: with composition off, SetWindowDisplayAffinity fails with
error 8 for every value, so anything testing screen-capture protection is
testing nothing -- and Windows 7 forces the Basic theme while the install is
not activated, which is exactly the state a throwaway test VM is usually in.

Two shapes in the DWM check are load-bearing and are commented as such. Under
guestcontrol, redirecting PowerShell's stdout to a file (or capturing it with
for /f) hangs the run until the host times out, so PowerShell prints the verdict
and the batch does not capture it. And the if/else must stay on ONE line: split
across two, PowerShell treats the file as an incomplete command and waits on
stdin forever. Two plausible cheaper checks are also wrong here, measured, and
are called out so nobody re-introduces them: dwm.exe keeps running with
composition off, and HKCU\...\DWM\Composition is the stored preference rather
than the live state. Both report ENABLED while the API returns false.

The elevated half is skipped with a notice rather than attempted, because a
guestcontrol-launched process gets a UAC-filtered token even for an account in
Administrators and cannot elevate itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLgzr9B13msJhCLpnmjNJS

README.md
setup-windows-7-test-env.bat [new file with mode: 0644]

index dfe024e6efa0f2594889dcfe22b7e2875302e414..6544500334e67d3930539cb2877d460d5437536b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@ throwaway VM reachable from a Linux host.
 | `setup-windows.bat` | Entry point. Runs the winget installs, then launches the elevated half and prints its log, then runs the non-elevated script. |
 | `setup-windows-no-uac.ps1` | The non-elevated, per-user half: WinMerge and BinSkim on the user `PATH`, and the global git config (identity, plus `core.sshCommand`). Can also be run directly from an ordinary prompt. |
 | `setup-windows-with-uac.ps1` | The elevated half, started via UAC by the batch file. Enables `ssh-agent`, installs the OpenSSH Client and Server capabilities and starts `sshd`, unpacks the `rsync-windows` release zip for this architecture (`rsync.exe` plus the `ssh.exe` it runs) into `C:\Tools\rsync` on the machine `PATH`, then installs Visual Studio 2022 Community with the required components, the WDK, and the Windows Performance Toolkit. Can also be run directly from an Administrator prompt. |
 | `setup-windows.bat` | Entry point. Runs the winget installs, then launches the elevated half and prints its log, then runs the non-elevated script. |
 | `setup-windows-no-uac.ps1` | The non-elevated, per-user half: WinMerge and BinSkim on the user `PATH`, and the global git config (identity, plus `core.sshCommand`). Can also be run directly from an ordinary prompt. |
 | `setup-windows-with-uac.ps1` | The elevated half, started via UAC by the batch file. Enables `ssh-agent`, installs the OpenSSH Client and Server capabilities and starts `sshd`, unpacks the `rsync-windows` release zip for this architecture (`rsync.exe` plus the `ssh.exe` it runs) into `C:\Tools\rsync` on the machine `PATH`, then installs Visual Studio 2022 Community with the required components, the WDK, and the Windows Performance Toolkit. Can also be run directly from an Administrator prompt. |
+| `setup-windows-7-test-env.bat` | Prepares a **Windows 7 VM** as a test target driven from the host by `VBoxManage guestcontrol`. Copy it into the guest and run it there; it is idempotent, so re-run it after any snapshot restore. The per-user half needs no UAC (crash-dialog suppression, no screen blanking, a staging directory, the shared folder on `Z:`); the machine-wide half is skipped with a notice unless run elevated inside the guest. It then reports what the box can actually test: DWM composition, printers, audio capture devices. |
 
 ## Usage
 
 
 ## Usage
 
diff --git a/setup-windows-7-test-env.bat b/setup-windows-7-test-env.bat
new file mode 100644 (file)
index 0000000..376d4dd
--- /dev/null
@@ -0,0 +1,163 @@
+@echo off
+setlocal
+
+rem ---------------------------------------------------------------------------
+rem setup-windows-7-test-env.bat - prepare a Windows 7 VM as a test target for
+rem native Windows software driven from the host by VBoxManage guestcontrol.
+rem
+rem Copy this file into the guest and run it there. It is idempotent: run it
+rem again after a rollback, or after any snapshot restore, to get the same box.
+rem
+rem Split in two halves, like the other provisioning scripts here:
+rem   - the per-user half runs as you and needs no UAC prompt
+rem   - the machine-wide half needs elevation and is SKIPPED (with a notice)
+rem     when this runs unelevated, so an unattended run never blocks on a prompt
+rem
+rem That split matters more than usual here: a guestcontrol-launched process gets
+rem a UAC-filtered token even for an account in Administrators, so the elevated
+rem half can only be done by running this from an interactive Administrator
+rem prompt inside the guest. Everything the host harness actually needs is in
+rem the per-user half.
+rem ---------------------------------------------------------------------------
+
+echo(
+echo ============================================================
+echo  Windows 7 test-target setup
+echo ============================================================
+
+rem --- Are we elevated? "net session" is the cheapest reliable probe. ---
+set "ELEVATED=0"
+net session >nul 2>&1
+if "%ERRORLEVEL%"=="0" set "ELEVATED=1"
+
+rem === PER-USER HALF (no UAC needed) =========================================
+
+echo(
+echo [user] Suppressing crash/hard-error dialogs
+rem A modal Windows Error Reporting dialog in the guest blocks a guestcontrol
+rem call until its timeout: the run looks like a hang, and a harness that scores
+rem a timeout as a failure will invent bugs that are not there. DontShowUI makes
+rem a crashing test process die immediately and return its exit code instead.
+reg add "HKCU\Software\Microsoft\Windows\Windows Error Reporting" /v DontShowUI /t REG_DWORD /d 1 /f >nul
+if errorlevel 1 echo   WARN: could not set DontShowUI
+
+echo [user] Disabling the screen saver and monitor blanking
+rem The host watches this VM's screen with "VBoxManage controlvm screenshotpng".
+rem A blanked screen makes every screenshot useless.
+reg add "HKCU\Control Panel\Desktop" /v ScreenSaveActive /t REG_SZ /d 0 /f >nul
+reg add "HKCU\Control Panel\Desktop" /v ScreenSaverIsSecure /t REG_SZ /d 0 /f >nul
+reg add "HKCU\Control Panel\Desktop" /v SCRNSAVE.EXE /t REG_SZ /d "" /f >nul 2>&1
+
+echo [user] Creating the staging directory C:\bb
+if not exist "C:\bb" mkdir "C:\bb"
+if not exist "C:\bb" echo   WARN: could not create C:\bb
+
+echo [user] Mapping Z: to the VirtualBox shared folder "Downloads"
+rem Bulk file transfer over a shared folder is far faster than a copyto per file.
+rem The mapping is per-user and must be re-made in each new interactive session,
+rem which is exactly why it lives in this script rather than in a host-side note.
+if exist Z:\ goto :zdone
+net use Z: \vboxsvr\Downloads /persistent:yes >nul 2>&1
+if errorlevel 1 echo   WARN: could not map Z: - is the shared folder attached to this VM?
+:zdone
+
+rem === MACHINE-WIDE HALF (needs elevation) ===================================
+
+if "%ELEVATED%"=="0" goto :skipadmin
+
+echo(
+echo [admin] Suppressing the system hard-error dialog (ErrorMode=2)
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\Windows" /v ErrorMode /t REG_DWORD /d 2 /f >nul
+if errorlevel 1 echo   WARN: could not set ErrorMode
+
+echo [admin] Disabling sleep and monitor timeout on AC
+powercfg -change -monitor-timeout-ac 0 >nul 2>&1
+powercfg -change -standby-timeout-ac 0 >nul 2>&1
+powercfg -change -disk-timeout-ac 0 >nul 2>&1
+powercfg -change -hibernate-timeout-ac 0 >nul 2>&1
+
+echo [admin] Turning off Windows Update automatic install
+rem An update reboot in the middle of a test run destroys the run and, worse,
+rem silently changes the system under test between two comparable results.
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v AUOptions /t REG_DWORD /d 1 /f >nul 2>&1
+goto :adminend
+
+:skipadmin
+echo(
+echo [admin] SKIPPED - this process is not elevated.
+echo         Run this script from an Administrator prompt INSIDE the guest to
+echo         apply: ErrorMode=2, sleep/monitor timeouts, Windows Update policy.
+echo         A guestcontrol-launched process cannot elevate itself, so these
+echo         cannot be done from the host harness.
+:adminend
+
+rem === READINESS REPORT ======================================================
+rem Everything below only reports. A test that silently runs against a box
+rem missing a device reads as "the software under test refused" when the truth is
+rem "this VM never had one" - so the harness must know, up front, what is here.
+
+echo(
+echo ============================================================
+echo  Readiness
+echo ============================================================
+echo(
+echo -- OS --
+ver
+echo arch=%PROCESSOR_ARCHITECTURE%  user=%USERNAME%  elevated=%ELEVATED%
+
+echo(
+echo -- Desktop Window Manager composition --
+rem SetWindowDisplayAffinity requires DWM composition. With composition OFF it
+rem fails with error 8 for every value, so any screen-capture protection under
+rem test is a silent no-op and its checks fail for a reason that has nothing to
+rem do with the code. Windows 7 runs the Basic theme (composition off) whenever
+rem the install is not activated.
+rem
+rem Ask the API, not a proxy for it. Two plausible-looking shortcuts are both
+rem WRONG on this box, measured: dwm.exe keeps running with composition off, and
+rem HKCU\...\DWM\Composition is the stored preference, not the live state. Both
+rem say ENABLED while DwmIsCompositionEnabled returns false.
+rem
+rem Two shapes to keep, both learned the hard way against guestcontrol:
+rem   - PowerShell PRINTS the verdict; the batch does not capture it. Redirecting
+rem     its stdout to a file, or capturing through for /f, hangs the whole run
+rem     until the host's timeout fires.
+rem   - the if/else is ONE line. Split across two, PowerShell treats the file as
+rem     an incomplete command, waits on stdin and never exits. The <nul below is
+rem     belt and braces for that whole class of hang.
+set "DWMPS=%TEMP%\w7env-dwm.ps1"
+> "%DWMPS%" echo Add-Type -TypeDefinition @^"
+>>"%DWMPS%" echo using System;
+>>"%DWMPS%" echo using System.Runtime.InteropServices;
+>>"%DWMPS%" echo public class D { [DllImport("dwmapi.dll")] public static extern int DwmIsCompositionEnabled(out bool e); }
+>>"%DWMPS%" echo ^"@
+>>"%DWMPS%" echo $e = $false
+>>"%DWMPS%" echo [void][D]::DwmIsCompositionEnabled([ref]$e)
+>>"%DWMPS%" echo if ($e) { "  composition = ENABLED - screen-capture affinity is testable." } else { "  composition = DISABLED - SetWindowDisplayAffinity fails with error 8 for every value, so a screen-capture-protection test here is testing nothing. Windows 7 forces the Basic theme while the install is not activated; activate it to test that path." }
+powershell -NoProfile -ExecutionPolicy Bypass -File "%DWMPS%" <nul
+del "%DWMPS%" >nul 2>&1
+
+echo(
+echo -- Printers (a print test needs at least one) --
+rem wmic, not PowerShell: no quoting to get wrong, and it is in the base install.
+wmic printer get Name,Default /format:table 2>nul | findstr /R /V "^$"
+if errorlevel 1 echo   NONE - print tests will report "could not create a printer DC"
+
+echo(
+echo -- Audio capture devices (a microphone test needs at least one) --
+wmic sounddev get Name,Status /format:table 2>nul | findstr /R /V "^$"
+if errorlevel 1 echo   NONE - enable audio for this VM in its VirtualBox settings
+
+echo(
+echo -- Shared folder --
+if exist Z:\ (echo   Z: mapped) else (echo   Z: NOT mapped)
+
+echo(
+echo -- Staging directory --
+if exist C:\bb (echo   C:\bb present) else (echo   C:\bb MISSING)
+
+echo(
+echo ============================================================
+echo  Done. Re-run this after any snapshot restore.
+echo ============================================================
+endlocal