Skip to content

Commit 710ff55

Browse files
Use virtual-display-rs driver in CI
Replace the Parsec VDD setup with virtual-display-rs in the CI workflow: download and extract the virtual-display-rs release, install the MSI via msiexec, and invoke a new PowerShell helper. Remove the old scripts/parsec-vdd.ps1 helper and add scripts/virtual-display-rs.ps1 which configures distinct virtual monitor modes and sends a DriverNotify payload over the driver's named pipe (no keepalive required). Adjusted the CI PowerShell invocation and shortened the post-install wait time.
1 parent aed2f3c commit 710ff55

3 files changed

Lines changed: 74 additions & 293 deletions

File tree

.github/workflows/ci.yml

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -131,23 +131,34 @@ jobs:
131131
}
132132
}
133133
134-
# install Parsec VDD driver silently
135-
DownloadFile `
136-
-Uri "https://builds.parsec.app/vdd/parsec-vdd-0.45.0.0.exe" `
137-
-OutFile "parsec-vdd-0.45.0.0.exe"
138-
Start-Process -FilePath ".\parsec-vdd-0.45.0.0.exe" -ArgumentList "/S" -Wait
139-
140-
# add virtual displays and keep them alive via a background process.
141-
# the script mirrors parsec-vdd.h via Win32 P/Invoke and runs a
142-
# keepalive loop, which is required to prevent the driver from
143-
# unplugging the displays after ~1 second.
144-
$scriptPath = Join-Path $env:GITHUB_WORKSPACE "scripts\parsec-vdd.ps1"
134+
# install virtual-display-rs driver
135+
# install virtual-display-rs driver
136+
$vdaRepo = "https://github.com/MolotovCherry/virtual-display-rs"
137+
$vdaZipUrl = "$vdaRepo/releases/download/v0.3.1/virtual-desktop-driver-installer-x64.zip"
138+
DownloadFile -Uri $vdaZipUrl -OutFile "virtual-display-rs.zip"
139+
140+
Write-Information "Download complete, extracting archive..." -InformationAction Continue
141+
Expand-Archive -Path "virtual-display-rs.zip" -DestinationPath "virtual-display-rs"
142+
$msi = Get-ChildItem -Path "virtual-display-rs" -Filter "*.msi" -Recurse | Select-Object -First 1
143+
Write-Information "Found installer: $($msi.FullName)" -InformationAction Continue
144+
Write-Information "Running msiexec..." -InformationAction Continue
145+
Start-Process -FilePath "msiexec.exe" `
146+
-ArgumentList "/i", $msi.FullName, "/qn", "/norestart", "REBOOT=ReallySuppress" `
147+
-Wait
148+
Write-Information "Driver installed" -InformationAction Continue
149+
150+
# add virtual displays with distinct resolutions so Windows can tell them apart.
151+
# the driver is a persistent Windows service with a named pipe API - no keepalive needed.
152+
$scriptPath = Join-Path $env:GITHUB_WORKSPACE "scripts\virtual-display-rs.ps1"
145153
$pwsh = Join-Path $env:SystemRoot "System32\WindowsPowerShell\v1.0\powershell.exe"
146-
Start-Process -FilePath $pwsh `
147-
-ArgumentList "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", $scriptPath, "-DisplayCount", "2" `
148-
-WindowStyle Hidden
149-
# allow time for displays to be added, resolutions set, and registered by Windows
150-
Start-Sleep -Seconds 10
154+
Write-Information "Configuring virtual displays..." -InformationAction Continue
155+
& $pwsh -NonInteractive -ExecutionPolicy Bypass -File $scriptPath -DisplayCount 2
156+
Write-Information "Virtual displays configured" -InformationAction Continue
157+
158+
# allow time for displays to be registered by Windows
159+
Write-Information "Waiting for displays to register..." -InformationAction Continue
160+
Start-Sleep -Seconds 5
161+
Write-Information "Prepare tests complete" -InformationAction Continue
151162
152163
- name: Setup python
153164
id: setup-python

scripts/parsec-vdd.ps1

Lines changed: 0 additions & 277 deletions
This file was deleted.

scripts/virtual-display-rs.ps1

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
param (
2+
[Parameter(Mandatory = $true)]
3+
[int]$DisplayCount
4+
)
5+
6+
# each display gets a distinct resolution so Windows can distinguish them
7+
$resolutions = @(
8+
@{ width = 1920; height = 1080; refresh_rates = @(60) },
9+
@{ width = 1280; height = 720; refresh_rates = @(60) },
10+
@{ width = 1600; height = 900; refresh_rates = @(60) }
11+
)
12+
13+
$monitors = @()
14+
for ($i = 0; $i -lt $DisplayCount; $i++) {
15+
$res = $resolutions[$i % $resolutions.Count]
16+
$monitors += @{
17+
id = [uint32]$i
18+
name = "VDD$i"
19+
enabled = $true
20+
modes = @(@{
21+
width = [uint32]$res.width
22+
height = [uint32]$res.height
23+
refresh_rates = @([uint32]$res.refresh_rates[0])
24+
})
25+
}
26+
}
27+
28+
# send {"DriverNotify": [...monitors...]} over the named pipe
29+
$json = [System.Text.Json.JsonSerializer]::Serialize(
30+
@{ DriverNotify = $monitors },
31+
[System.Text.Json.JsonSerializerOptions]@{ WriteIndented = $false }
32+
)
33+
34+
Write-Information "Payload: $json" -InformationAction Continue
35+
36+
Write-Information "Connecting to named pipe..." -InformationAction Continue
37+
$pipe = New-Object System.IO.Pipes.NamedPipeClientStream(".", "virtualdisplaydriver", [System.IO.Pipes.PipeDirection]::InOut)
38+
$pipe.Connect(5000)
39+
$pipe.ReadMode = [System.IO.Pipes.PipeTransmissionMode]::Message
40+
Write-Information "Connected" -InformationAction Continue
41+
42+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($json)
43+
$pipe.Write($bytes, 0, $bytes.Length)
44+
$pipe.Flush()
45+
$pipe.Dispose()
46+
47+
Write-Information "Sent monitor config for $DisplayCount display(s)" -InformationAction Continue

0 commit comments

Comments
 (0)