mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-10-08 11:39:10 +11:00
* perf: keep UI startup responsive * test: make favicon checks runner-safe * fix: qualify favicon visibility state * test: isolate favicon visibility fixture * fix: enforce total favicon deadline * fix: address favicon review feedback * fix: recognize disabled SSH firewall rule * perf: restore favicon download throughput * docs: allow public PR review uploads * perf: restore overlapping favicon loading
123 lines
4.2 KiB
PowerShell
123 lines
4.2 KiB
PowerShell
function Write-WinUtilLog {
|
|
<#
|
|
|
|
.SYNOPSIS
|
|
Writes a timestamped WinUtil log entry to the active session log.
|
|
|
|
.DESCRIPTION
|
|
Called from the interface thread and from every job body. When Start-Transcript owns the
|
|
active session log, entries go through the host so the transcript records them without a
|
|
competing file write. Standalone callers use a named mutex to serialize direct appends.
|
|
|
|
.PARAMETER Message
|
|
The message to write.
|
|
|
|
.PARAMETER Level
|
|
The severity level for the log entry.
|
|
|
|
.PARAMETER Component
|
|
The WinUtil component producing the log entry.
|
|
|
|
#>
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Message,
|
|
|
|
[ValidateSet("INFO", "WARN", "ERROR", "DEBUG")]
|
|
[string]$Level = "INFO",
|
|
|
|
[string]$Component = "WinUtil",
|
|
|
|
# Continuation of an error already counted, such as a stack frame
|
|
[switch]$Detail
|
|
)
|
|
|
|
# UI performance diagnostics are useful to developers but are too noisy for the release
|
|
# transcript. Compile.ps1 stamps local builds so DEBUG output cannot leak into CI artifacts.
|
|
if ($Level -eq "DEBUG" -and ($null -eq $sync -or -not $sync.IsLocalCompile)) {
|
|
return
|
|
}
|
|
|
|
if ($Level -eq "ERROR" -and -not $Detail -and $null -ne $sync.LoggedErrors) {
|
|
$null = $sync.LoggedErrors.Add("[$Component] $Message")
|
|
}
|
|
|
|
if ($Level -eq "ERROR" -and -not $Detail -and $global:WinUtilIsJobWorker) {
|
|
$global:WinUtilJobErrorCount++
|
|
}
|
|
|
|
try {
|
|
$logPath = $null
|
|
$transcriptPath = $null
|
|
if ($null -ne $sync -and $sync.ContainsKey("logPath")) {
|
|
$logPath = $sync.logPath
|
|
}
|
|
|
|
if ($null -ne $sync -and $sync.ContainsKey("transcriptPath")) {
|
|
$transcriptPath = $sync.transcriptPath
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($logPath) -and -not [string]::IsNullOrWhiteSpace($transcriptPath)) {
|
|
$logPath = $transcriptPath
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($logPath) -and $null -ne $sync -and $sync.ContainsKey("winutildir")) {
|
|
$logDirectory = Join-Path $sync.winutildir "logs"
|
|
$logPath = Join-Path $logDirectory "winutil_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").log"
|
|
$sync.logPath = $logPath
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($logPath) -and -not [string]::IsNullOrWhiteSpace($env:LocalAppData)) {
|
|
if ([string]::IsNullOrWhiteSpace($script:WinUtilLogPath)) {
|
|
$logDirectory = Join-Path (Join-Path $env:LocalAppData "winutil") "logs"
|
|
$script:WinUtilLogPath = Join-Path $logDirectory "winutil_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").log"
|
|
}
|
|
$logPath = $script:WinUtilLogPath
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($logPath)) {
|
|
return
|
|
}
|
|
|
|
$logDirectory = Split-Path -Path $logPath -Parent
|
|
if (-not (Test-Path $logDirectory)) {
|
|
New-Item -Path $logDirectory -ItemType Directory -Force | Out-Null
|
|
}
|
|
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"
|
|
$line = "[$timestamp] [$Level] [$Component] $Message"
|
|
|
|
if (-not [string]::IsNullOrWhiteSpace($transcriptPath) -and $logPath -eq $transcriptPath) {
|
|
Write-Host $line
|
|
return
|
|
}
|
|
|
|
$mutex = [System.Threading.Mutex]::new($false, "WinUtilSessionLog")
|
|
$held = $false
|
|
try {
|
|
try {
|
|
$held = $mutex.WaitOne(2000)
|
|
} catch [System.Threading.AbandonedMutexException] {
|
|
# A thread died holding the mutex; ownership transfers to us either way
|
|
$held = $true
|
|
}
|
|
|
|
if (-not $held) {
|
|
# Writing anyway is what interleaves lines, and the wait only times out when
|
|
# contention is at its worst
|
|
Write-Host $line
|
|
return
|
|
}
|
|
|
|
Add-Content -Path $logPath -Value $line -Encoding UTF8 -ErrorAction Stop
|
|
} catch [System.IO.IOException] {
|
|
Write-Host $line
|
|
} finally {
|
|
if ($held) { $mutex.ReleaseMutex() }
|
|
$mutex.Dispose()
|
|
}
|
|
} catch {
|
|
Write-Warning "Unable to write WinUtil log entry: $($_.Exception.Message)"
|
|
}
|
|
}
|