67 lines
3.7 KiB
Python
67 lines
3.7 KiB
Python
"""Run the scoped VDD mode probe in VM100's already logged-in user session."""
|
|
import argparse
|
|
import base64
|
|
from pathlib import Path
|
|
import runpy
|
|
import sys
|
|
import re
|
|
|
|
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("action", choices=["Query", "List", "Apply", "Restore"])
|
|
parser.add_argument("--hz", type=int, default=60)
|
|
parser.add_argument("--backup-tag", default="", help="Separate backup for this verification run")
|
|
args = parser.parse_args()
|
|
if not 24 <= args.hz <= 240:
|
|
parser.error("--hz must be in 24..240")
|
|
if args.backup_tag and not re.fullmatch(r"[A-Za-z0-9_-]{1,64}", args.backup_tag):
|
|
parser.error("--backup-tag must contain 1..64 letters, digits, underscores or hyphens")
|
|
backup_name = "display-before" + ("-" + args.backup_tag if args.backup_tag else "") + ".json"
|
|
root = Path(__file__).resolve().parent
|
|
term = runpy.run_path(str(root / "pve_term_exec.py"))
|
|
vm = runpy.run_path(str(root / "pve_vm.py"))
|
|
ticket, csrf = term["login"]()
|
|
state = vm["api"]("/api2/json/nodes/starhe/qemu/100/status/current", ticket=ticket)
|
|
if state.get("status") != "running":
|
|
sys.exit("VM100 is not running; no task or display configuration changed")
|
|
payload = base64.b64encode((root / "set-vdi-display-mode.ps1").read_bytes()).decode()
|
|
command = r"""
|
|
$ErrorActionPreference='Stop'
|
|
$folder='C:\ProgramData\VDI\mouse-optimization'
|
|
$task='VDIMouseDisplayProbe'
|
|
if(Get-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue) { throw 'Probe task already exists' }
|
|
$user=(Get-CimInstance Win32_ComputerSystem).UserName
|
|
if(-not $user) { throw 'No interactive user' }
|
|
New-Item -ItemType Directory -Force $folder | Out-Null
|
|
$acl=Get-Acl -LiteralPath $folder
|
|
$rule=New-Object Security.AccessControl.FileSystemAccessRule($user,'Modify','ContainerInherit,ObjectInherit','None','Allow')
|
|
$acl.SetAccessRule($rule)
|
|
Set-Acl -LiteralPath $folder -AclObject $acl
|
|
[IO.File]::WriteAllBytes("$folder\mode.ps1",[Convert]::FromBase64String('__VDI_PAYLOAD__'))
|
|
$run="try { & '$folder\mode.ps1' -Action __VDI_ACTION__ -RefreshRate __VDI_HZ__ -BackupPath '$folder\__VDI_BACKUP__' | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt' } catch { `$_ | Out-String | Out-File -Encoding utf8 -Width 300 '$folder\mode-result.txt'; exit 1 }"
|
|
$encoded=[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($run))
|
|
$action=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -EncodedCommand $encoded"
|
|
$principal=New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Limited
|
|
$settings=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 1)
|
|
Register-ScheduledTask -TaskName $task -Action $action -Principal $principal -Settings $settings | Out-Null
|
|
try {
|
|
Start-ScheduledTask -TaskName $task
|
|
Start-Sleep -Seconds 2
|
|
for($i=0;$i -lt 20;$i++) {
|
|
if((Get-ScheduledTask -TaskName $task).State -ne 'Running') { break }
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
if((Get-ScheduledTask -TaskName $task).State -eq 'Running') { throw 'Probe timed out' }
|
|
Get-Content "$folder\mode-result.txt"
|
|
'task_result='+(Get-ScheduledTaskInfo -TaskName $task).LastTaskResult
|
|
} finally {
|
|
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
|
|
Unregister-ScheduledTask -TaskName $task -Confirm:$false
|
|
}
|
|
""".replace("__VDI_ACTION__", args.action).replace("__VDI_HZ__", str(args.hz)).replace("__VDI_BACKUP__", backup_name).replace("__VDI_PAYLOAD__", payload)
|
|
out, error = vm["agent"](ticket, csrf, ["powershell.exe", "-NoProfile", "-Command", command])
|
|
print(out)
|
|
if error or "task_result=0" not in out:
|
|
print(error, file=sys.stderr)
|
|
sys.exit(1)
|