param( [Parameter(Mandatory=$true)][string]$Executable, [Parameter(Mandatory=$true)][string]$OutputDirectory, [ValidateSet(8,24,72)][int]$Hours = 72, [ValidateRange(1,3600)][int]$SampleSeconds = 60 ) $ErrorActionPreference = 'Stop' $exe = (Resolve-Path $Executable).Path $directory = [IO.Path]::GetFullPath($OutputDirectory) if (Test-Path $directory) { throw 'Use a new output directory; endurance evidence is never overwritten.' } [IO.Directory]::CreateDirectory($directory) | Out-Null $utf8 = New-Object Text.UTF8Encoding($false) $started = [DateTimeOffset]::UtcNow $info = @{ StartedAt=$started.ToString('o') ExpectedFinish=$started.AddHours($Hours).ToString('o') Hours=$Hours SampleSeconds=$SampleSeconds Executable=$exe BinarySha256=(Get-FileHash $exe -Algorithm SHA256).Hash SessionId=[Diagnostics.Process]::GetCurrentProcess().SessionId OperatingSystem=[Environment]::OSVersion.VersionString WritesMessages=$false } [IO.File]::WriteAllText("$directory\run-info.json", ($info | ConvertTo-Json), $utf8) $code = 1 try { & $exe endurance --hours $Hours --sample-seconds $SampleSeconds --output "$directory\metrics" | ForEach-Object { [IO.File]::AppendAllText("$directory\console.json", $_ + [Environment]::NewLine, $utf8) } $code = $LASTEXITCODE } catch { [IO.File]::WriteAllText("$directory\launcher-error.txt", $_.Exception.GetType().FullName, $utf8) } finally { [IO.File]::WriteAllText("$directory\exit-code.txt", [string]$code, $utf8) [IO.File]::WriteAllText("$directory\finished-at.txt", [DateTimeOffset]::UtcNow.ToString('o'), $utf8) } exit $code