. "$PSScriptRoot/Config.ps1"; . "$PSScriptRoot/../Types/OneShotTask.ps1"; . "$PSScriptRoot/../../Windows/Scripts/PowerManagement.ps1"; $null = New-Module { . "$PSScriptRoot/../Types/OneShotTask.ps1"; $logName = "Application"; $oneShotTrigger = 1337; $taskOption = "OneShotTask"; # ToDo: Store "ProgramData/PortValhalla" path somewhere as const $errorPath = "$env:ProgramData/PortValhalla/error.txt"; $taskSetter = { param([OneShotTask] $Task) Set-SetupOption $taskOption ([string]$Task); }; function Start-Operation { param( [scriptblock] $Action ) $Global:ErrorActionPreference = 'Inquire'; $env:WSLENV = "CONFIG_MODULE/p"; if ($env:CONFIG_MODULE) { $env:CONFIG_MODULE = Resolve-Path $env:CONFIG_MODULE; } New-Alias "sudo" gsudo; & $Action; } <# .SYNOPSIS Gets the current OneShot task. #> function Get-OneShotTask { [OneShotTask](Get-SetupOption $taskOption); } <# .SYNOPSIS Registers a task for listening to OneShot invocations. #> function Enable-OneShotListener { $tempTask = "PortValhalla Temp"; $action = New-ScheduledTaskAction -Execute "pwsh" -Argument (Get-StartupArguments); schtasks /Create /SC ONEVENT /EC $logName /MO "*[System[Provider[@Name='$logName'] and EventID=$($oneShotTrigger)]]" /TR cmd.exe /TN $tempTask; $trigger = (Get-ScheduledTask $tempTask).Triggers; $principal = New-ScheduledTaskPrincipal -UserId (Get-SetupUser) -RunLevel Highest; $task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger; $null = Register-ScheduledTask -Force "PortValhalla OneShot" -InputObject $task; $null = Unregister-ScheduledTask -Confirm:$false $tempTask; } <# .SYNOPSIS Invokes a one-shot task. .PARAMETER Task The task to run. #> function Invoke-OneShot { param( [OneShotTask] $Task ) $currentStage = Get-Stage; Set-Stage ([SetupStage]::OneShot); & $taskSetter $Task; $job = & { $identifier = "EventLog$oneShotTrigger"; $log = [System.Diagnostics.EventLog]::new($logName); $null = Register-ObjectEvent -InputObject $log -EventName EntryWritten -Action { $entry = $event.SourceEventArgs.Entry; if ($entry.EventID -eq $oneShotTrigger) { $null = New-Event -SourceIdentifier $identifier; } }; Start-Job { Wait-Event -SourceIdentifier $identifier; }; }; Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "Starting OneShot task ``$(Get-OneShotTask)``…"; $null = Wait-Job $job; Set-Stage $currentStage; if (Test-Path $errorPath) { $errorMessage = Get-Content $errorPath; Remove-Item $errorPath; throw $errorMessage; } } # ToDo: Store Run-OneShot and Receive-OneShot somewhere else in Windows folder <# .SYNOPSIS Executes the specified action and notifies the OneShot task executor. #> function Start-OneShot { param( [scriptblock] $Action ) try { Start-Operation @PSBoundParameters; } catch { Set-Content -Path $errorPath -Value $Error; } finally { Set-Stage ([SetupStage]::Idle); Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished."; } } };