# logging.fallback.ps1 This file implements SAMY’s fallback logging functions used across the project. It supports: - Console logging (color-coded) - In-memory log caching (for UI/diagnostics) - Optional file logging (UTF-8 **without BOM**) - Optional Windows Event Log logging, including: - first-run creation of the log/source (when elevated) - resolving “source bound to the wrong log” problems --- ## Regions overview ### Globals **What it does** - Initializes shared global state used by logging: - `LogCache`: an `ArrayList` of log entries created during execution. - `EventSinkCache`: a `Hashtable` caching resolved Event Log sinks so we do not repeatedly initialize/bind. **Why it exists** - Makes log output available to UI or post-run summaries. - Prevents repeated Event Log setup attempts and repeated warnings. --- ### Helpers: Formatting + File **What it does** - `Get-LogColor(Level)`: maps `Info/Warning/Error/Success/General` to console colors. - `Get-EventIdForLevel(Level, CustomEventID)`: returns default Event IDs by level unless overridden. - `Get-EventEntryTypeForLevel(Level)`: maps levels to Event Log entry types. - `Append-Utf8NoBomLine(Path, Line)`: appends a line to a file using UTF-8 **without BOM**. **Why it exists** - Keeps the main logging functions readable. - Ensures runtime log files comply with the repository encoding rule (UTF-8 no BOM). --- ### Helpers: Event Log Binding **Background** Windows Event Log has a key constraint: A **Source** can only be registered to **one** Log at a time. Example: - If source `SVMSP_Module` is registered to `Application`, you cannot write with: `Write-EventLog -LogName "SVSMSP Events" -Source "SVMSP_Module"` until that binding is repaired or avoided. **What it does** - `Test-IsAdmin()`: checks if the current PowerShell session is elevated. - `Initialize-EventLogBinding(DesiredLog, DesiredSource, ConflictPolicy)`: returns an effective `{ LogName, Source, IsAdmin }` that is safe to use for `Write-EventLog`. **ConflictPolicy** If `DesiredSource` exists but is bound to a different log, one of these policies applies: - `Repair` (default) - Removes the existing source registration from its current log - Recreates it under `DesiredLog` - Requires elevation - Best when you want **all SAMY logs in one custom log** - `Unique` - Creates a new SAMY-specific source under `DesiredLog` (e.g., `SVMSP_Module.SAMY`, `SVMSP_Module.SAMY2`, etc.) - Does not delete anything - Requires elevation to create the new source - Best when you want **no deletion / no rebinding risk** - `Follow` - Uses whichever log the source is already bound to - Never deletes anything - May log to `Application` if that’s where the source already exists - Best when you want **maximum safety and minimum changes** **Non-admin behavior** If not elevated and the desired source does not exist, the code falls back to: - `LogName = Application` - `Source = Windows PowerShell` This avoids trying to create custom Event Log sources without admin rights. --- ### Public: Write-LogHelper **What it does** This is the core fallback logger. Always does: - Writes a formatted message to console (with color) - Adds an entry to `Global:LogCache` Optionally does: - File logging (when `-LogFile` is provided) - Event Log logging (when `-LogToEvent` is set) **Event Log caching** To avoid repeating setup work, the function caches the resolved Event Log sink: - Key format: `"$EventLog|$EventSource|$EventLogConflictPolicy"` - Cached value includes: - `Ready` (boolean) - `LogName` (effective log to write to) - `Source` (effective source to write with) **Parameters that matter most** - `-Message`: text to log - `-Level`: affects console color, EventId, EntryType - `-TaskCategory`: included in formatted message and event message - `-LogToEvent`: enable/disable Event Log writes - `-EventLog`, `-EventSource`: desired Event Log sink - `-EventLogConflictPolicy`: `Repair`, `Unique`, or `Follow` --- ### Public: Write-LogHybrid **What it does** A wrapper for compatibility. Behavior: - If a preferred logger function `Write-Log` exists, it calls that. - Otherwise it calls `Write-LogHelper`. **Why it exists** - Lets SAMY swap logging implementations without changing all call sites. --- ## Typical usage examples ### Console only ```powershell Write-LogHybrid -Message "Starting SAMY" -Level Info -TaskCategory "Startup"