验证:补充独立光标可行性POC

This commit is contained in:
songyiming committed 2026-11-03 17:49:31 +08:00
1 parent b29b59c62f
commit 1439028833
49 files changed
+957 -1

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
"""Scoped VM100 interactive cursor exporter. No new network listener or system cursor theme."""
import argparse
import base64
import json
from pathlib import Path
import runpy
import sys
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("action", choices=["start", "status", "export", "stop"])
parser.add_argument("--output", type=Path)
args = parser.parse_args()
root = Path(__file__).resolve().parent
t = runpy.run_path(str(root / "pve_term_exec.py"))
v = runpy.run_path(str(root / "pve_vm.py"))
ticket, csrf = t["login"]()
if v["api"]("/api2/json/nodes/starhe/qemu/100/status/current", ticket=ticket).get("status") != "running":
sys.exit("VM100 is not running")
command = r"$ErrorActionPreference='Stop'; $folder='C:\ProgramData\VDI\cursor-poc-20261103'; $task='VDICursorPOC'; "
if args.action == "start":
payload = base64.b64encode((root / "cursor-poc-host.ps1").read_bytes()).decode()
command += r"""
if(Get-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue) { throw 'Probe 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 $folder
$acl.SetAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($user,'Modify','ContainerInherit,ObjectInherit','None','Allow')))
Set-Acl $folder $acl
Remove-Item "$folder\error.txt","$folder\state.json","$folder\shapes.json" -ErrorAction SilentlyContinue
[IO.File]::WriteAllBytes("$folder\probe.ps1",[Convert]::FromBase64String('__PAYLOAD__'))
$a=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -STA -ExecutionPolicy Bypass -WindowStyle Hidden -File $folder\probe.ps1"
$p=New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Limited
$s=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 9)
Register-ScheduledTask -TaskName $task -Action $a -Principal $p -Settings $s | Out-Null
Start-ScheduledTask -TaskName $task
Start-Sleep -Seconds 3
if(Test-Path "$folder\error.txt") { throw (Get-Content "$folder\error.txt" -Raw) }
if(-not(Test-Path "$folder\shapes.json")) { throw 'No fresh cursor export' }
'Cursor probe started'
""".replace("__PAYLOAD__", payload)
elif args.action == "export":
command += 'Get-Content "$folder\\shapes.json" -Raw'
elif args.action == "status":
command += r"""
Get-Content "$folder\state.json" -Raw
Get-Content "$folder\clicks.csv"
Get-Content "$folder\states.csv"
Get-Content "$folder\error.txt" -ErrorAction SilentlyContinue
"""
else:
command += r"""
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
Unregister-ScheduledTask -TaskName $task -Confirm:$false -ErrorAction SilentlyContinue
if(Test-Path "$folder\pid.txt") {
$probePid=[int](Get-Content "$folder\pid.txt")
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$probePid"
if($process.CommandLine -like '*cursor-poc-20261103*') { Stop-Process -Id $probePid -ErrorAction SilentlyContinue }
}
'Cursor probe stopped'
"""
out, error = v["agent"](ticket, csrf, ["powershell.exe", "-NoProfile", "-Command", command])
if error or not out or out == "TIMEOUT":
sys.exit(error or out or "Empty guest-agent result")
if args.action == "export":
data = json.loads(out.lstrip("\ufeff"))
if args.output:
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(json.dumps(data, separators=(",", ":")), encoding="utf-8")
print(json.dumps([{k: s[k] for k in ("name", "width", "height", "hotX", "hotY", "monochrome", "invertedPixels")} for s in data["shapes"]]))
else:
print(out)