Skill v1.0.0
Trusted Publisher100/100version: "1.0.0" name: test-on-vm description: EXPERIMENTAL. Run locally built WinUI interaction tests on a Hyper-V VM through PowerShell Direct. Use when asked to run WinUI tests on a local VM.
Run WinUI Tests on a Hyper-V VM
Run tools\run-tests-on-vm.ps1 through initrun.ps1. It refreshes the local test payload, deploys it to the VM, performs required machine setup, and runs tests on the VM's interactive desktop.
This skill and script are experimental and may not be stable.
Before You Run
Build the repository first. Follow the build skill:
.\initrun.ps1 .\build.cmd /q
Also verify:
- The VM is running with an unlocked desktop and a logged-in user.
- The caller is a local admin or a member of Hyper-V Administrators.
- The command uses
initial_waitof at least 180 seconds.
If Hyper-V permissions are missing, stop and ask the user to make the change themselves. Never run `Add-LocalGroupMember` or open an elevated shell on their behalf, even with their approval.
Tell the user to run whoami in their original, non-elevated PowerShell window and copy the account name. Then have them open a separate PowerShell (`pwsh`) window using Run as administrator and run this command, replacing <account-from-whoami> with the copied name:
Add-LocalGroupMember -Group 'Hyper-V Administrators' -Member '<account-from-whoami>'
Tell the user to sign out and back in afterward. Wait for them to confirm they have completed these steps before retrying the test.
The first run prompts for VM credentials in a separate window and caches them encrypted under ~\.winui-test. Use -ResetCredential to replace them.
Run Tests
# Run a specific test.\initrun.ps1 .\tools\run-tests-on-vm.ps1 -VMName <vm> <testname># Wildcard match.\initrun.ps1 .\tools\run-tests-on-vm.ps1 -VMName <vm> *CommandBar*# Force full copy instead of incremental.\initrun.ps1 .\tools\run-tests-on-vm.ps1 -VMName <vm> -FullCopy <testname># Stop a stuck test run.\initrun.ps1 .\tools\run-tests-on-vm.ps1 -VMName <vm> -Stop
Payload Rules
By default, the script runs test\CreateTestPayload.ps1 to refresh TestPayload\<flavor> from the current build outputs, then deploys changed files incrementally.
-FullCopystill refreshes the local payload, then copies all of it to the VM.- Use `-SkipPayload` rarely. It deploys the existing local payload without
refreshing it. Use it only when that payload is known to be current or when intentionally testing stale binaries. Never use it merely to save time.
Useful Options
| Option | Purpose | |
|---|---|---|
-Platform | x86, x64, or arm64; uses $env:BUILDPLATFORM, then defaults to x64 | |
-Configuration | chk or fre; uses $env:_BuildType, then defaults to chk | |
-FullCopy | Copy the full refreshed payload instead of only changes | |
-SkipPayload | Rare: deploy the existing payload without refreshing it | |
-SkipPrerun | Skip testmachine-prerun.cmd | |
-ForcePrerun | Run testmachine-prerun.cmd again | |
-Credential | Supply a PSCredential instead of using the prompt/cache | |
-ResetCredential | Clear the cached credential for this VM | |
-Stop | Stop the active test and clean up |
Troubleshooting
| Symptom | Cause | Fix | |
|---|---|---|---|
Could not launch app, foreground-window errors, or an empty UIA tree | VM desktop is locked or not visible | Keep the VM desktop unlocked and active | |
Failed to connect to VM | VM not running or wrong credentials | Start the VM; use -ResetCredential to re-enter credentials | |
| Permission error | Need Hyper-V Administrators membership | Stop and have the user follow the permission steps above | |
| Incomplete payload or prerun failure | Stale payload or partial deployment | Omit -SkipPayload; retry with -FullCopy if needed |
Crash Dumps
The first prerun configures full crash dumps under C:\dumps on the VM, with up to three dumps per process. Pull one back through PowerShell Direct:
$vmName = "<vm>"$credentialKey = $vmName -replace '[^a-zA-Z0-9]', '_'$cred = Import-Clixml (Join-Path $env:USERPROFILE ".winui-test\vmcred-$credentialKey.xml")$destination = Join-Path $env:TEMP "WinUIDumps"New-Item -ItemType Directory -Path $destination -Force | Out-Null$session = New-PSSession -VMName $vmName -Credential $credtry {Invoke-Command -Session $session { Get-ChildItem C:\dumps\*.dmp }Copy-Item -FromSession $session -Path "C:\dumps\<dump>.dmp" -Destination $destination}finally {Remove-PSSession $session}
For a quick local analysis:
cdb -z "$env:TEMP\WinUIDumps\<dump>.dmp" -c "!analyze -v; ~*k; q"