56 lines
2.9 KiB
Python
56 lines
2.9 KiB
Python
"""Query or detach extra Windows desktop outputs in VM100's interactive session."""
|
|
import argparse
|
|
import base64
|
|
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=["Query","Apply","Restore"])
|
|
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; nothing changed")
|
|
payload=base64.b64encode((root/"set-single-vdi-display.ps1").read_bytes()).decode()
|
|
command=r"""
|
|
$ErrorActionPreference='Stop'
|
|
$folder='C:\ProgramData\VDI\single-display-20261103'
|
|
$task='VDISingleDisplayProbe'
|
|
if(Get-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue) { throw '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 $folder
|
|
$acl.SetAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($user,'Modify','ContainerInherit,ObjectInherit','None','Allow')))
|
|
Set-Acl $folder $acl
|
|
[IO.File]::WriteAllBytes("$folder\single.ps1",[Convert]::FromBase64String('__PAYLOAD__'))
|
|
Remove-Item "$folder\result.txt" -ErrorAction SilentlyContinue
|
|
$run="try { & '$folder\single.ps1' -Action __ACTION__ | Out-File -Encoding utf8 -Width 500 '$folder\result.txt' } catch { `$_ | Out-String | Out-File -Encoding utf8 -Width 500 '$folder\result.txt'; exit 1 }"
|
|
$encoded=[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($run))
|
|
$a=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -EncodedCommand $encoded"
|
|
$p=New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Limited
|
|
$s=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 2)
|
|
Register-ScheduledTask -TaskName $task -Action $a -Principal $p -Settings $s | Out-Null
|
|
try {
|
|
Start-ScheduledTask -TaskName $task
|
|
Start-Sleep -Seconds 2
|
|
for($i=0;$i-lt 30;$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\result.txt" -Raw
|
|
'task_result='+(Get-ScheduledTaskInfo -TaskName $task).LastTaskResult
|
|
} finally {
|
|
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
|
|
Unregister-ScheduledTask -TaskName $task -Confirm:$false
|
|
}
|
|
""".replace("__PAYLOAD__",payload).replace("__ACTION__",args.action)
|
|
out,err=v["agent"](ticket,csrf,["powershell.exe","-NoProfile","-Command",command])
|
|
print(out)
|
|
if err or "task_result=0" not in out:
|
|
sys.exit(err or "Display operation did not succeed")
|