1param([string]$Binary, [switch]$Remove, [string]$User)
2$ErrorActionPreference = 'Stop'
3$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
4$principal = New-Object Security.Principal.WindowsPrincipal($identity)
5if (!$principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Run this installer as administrator to access the VirtIO serial port.' }
6if ($User) {
7 if (!$identity.IsSystem) { throw 'Only system provisioning can select another account.' }
8 $account = New-Object Security.Principal.NTAccount($env:COMPUTERNAME, $User)
9 $sid = $account.Translate([Security.Principal.SecurityIdentifier]).Value
10} else {
11 if ((Get-WmiObject Win32_ComputerSystem).UserName -ne $identity.Name) { throw 'Run this installer from the signed-in administrator account on the VM desktop.' }
12 $sid = $identity.User.Value
13}
14$directory = Join-Path $env:ProgramFiles 'Snowglobe\Guest'
15$destination = Join-Path $directory 'snowglobe-guest.exe'
16$service = New-Object -ComObject Schedule.Service
17$service.Connect()
18$folder = $service.GetFolder('\')
19$name = 'SnowglobeGuest-' + $sid
20if ($Remove) {
21 try { $folder.GetTask($name).Stop(0); $folder.DeleteTask($name, 0) } catch { if (Test-Path $destination) { throw } }
22 $used = $false
23 foreach ($task in $folder.GetTasks(1)) {
24 foreach ($action in $task.Definition.Actions) { if ($action.Path -eq $destination) { $used = $true } }
25 }
26 if (!$used -and (Test-Path $destination)) { Remove-Item $destination }
27 return
28}
29if (!$Binary) { throw 'Pass the path to the guest executable with -Binary.' }
30Get-WmiObject Win32_Process -Filter "name='snowglobe-guest.exe'" | Where-Object { $_.ExecutablePath -eq $destination } | ForEach-Object {
31 $process = Get-Process -Id $_.ProcessId -ErrorAction SilentlyContinue
32 if ($process) {
33 $process | Stop-Process -Force
34 if (!$process.WaitForExit(10000)) { throw 'The guest agent did not stop. Restart the VM and retry.' }
35 }
36}
37New-Item -ItemType Directory -Path $directory -Force | Out-Null
38Copy-Item -LiteralPath $Binary -Destination $destination -Force
39$task = $service.NewTask(0)
40$task.Principal.UserId = $sid
41$task.Principal.LogonType = 3
42$task.Principal.RunLevel = 1
43$task.Settings.ExecutionTimeLimit = 'PT0S'
44$task.Settings.DisallowStartIfOnBatteries = $false
45$task.Settings.StopIfGoingOnBatteries = $false
46$trigger = $task.Triggers.Create(9)
47$trigger.UserId = $sid
48$action = $task.Actions.Create(0)
49$action.Path = $destination
50$registered = $folder.RegisterTaskDefinition($name, $task, 6, $sid, $null, 3, $null)
51$registered.Run($null) | Out-Null