#requires -Version 5.1 [CmdletBinding()] param() $ErrorActionPreference = 'Stop' if ([Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT) { throw 'The Jun OS manager only runs on Windows.' } $script:PowerShellExe = @( (Join-Path $env:SystemRoot 'Sysnative\WindowsPowerShell\v1.0\powershell.exe'), (Join-Path $env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe') ) | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1 if (-not $script:PowerShellExe) { $script:PowerShellExe = 'powershell.exe' } # compiled (JunOS.exe) there's no $PSScriptRoot, the folder is # wherever the exe sits. the installer drops it in her folder, # next to start.ps1. $script:IsCompiled = -not $PSCommandPath -or $PSCommandPath.EndsWith('.exe', 'OrdinalIgnoreCase') $script:Root = if ($script:IsCompiled) { Split-Path -Parent ([Diagnostics.Process]::GetCurrentProcess().MainModule.FileName) } else { $PSScriptRoot } if ([Threading.Thread]::CurrentThread.GetApartmentState() -ne [Threading.ApartmentState]::STA) { if ($script:IsCompiled) { throw 'This build was compiled without -STA. Rebuild with tools/build-installer-exe.ps1 -Manager.' } Start-Process -FilePath $script:PowerShellExe -WindowStyle Hidden ` -ArgumentList '-NoProfile', '-ExecutionPolicy', 'Bypass', '-STA', '-File', "`"$PSCommandPath`"" exit } Add-Type -AssemblyName PresentationFramework Add-Type -AssemblyName PresentationCore Add-Type -AssemblyName WindowsBase # a second click on the shortcut would start a second window # racing the first one on start.ps1. one is enough. $script:Mutex = [Threading.Mutex]::new($false, 'Local\JunOS-Manager') if (-not $script:Mutex.WaitOne(0)) { exit } if (-not (Test-Path -LiteralPath (Join-Path $script:Root 'start.ps1'))) { [System.Windows.MessageBox]::Show( "start.ps1 isn't next to this program ($($script:Root)). Keep JunOS.exe inside the Jun OS folder.", 'Jun OS', 'OK', 'Error') | Out-Null exit 1 } if (-not ('JunProcessOutput' -as [type])) { Add-Type -TypeDefinition @' using System.Collections.Concurrent; using System.Diagnostics; public sealed class JunProcessOutput { public readonly ConcurrentQueue Lines = new ConcurrentQueue(); public void Attach(Process process) { process.OutputDataReceived += OnData; process.ErrorDataReceived += OnData; } private void OnData(object sender, DataReceivedEventArgs args) { if (args.Data != null) Lines.Enqueue(args.Data); } } '@ } [xml]$xaml = @' Ω