private/functions/Export-PowerStubConfiguration.ps1
|
<#
.SYNOPSIS Exports configuration to the configuration file. .DESCRIPTION Serializes the current configuration (excluding internal keys) to JSON and writes it to the config file using atomic write (temp + rename). .INPUTS None. You cannot pipe objects to this function. .OUTPUTS None. #> function Export-PowerStubConfiguration { $noExport = Get-PowerStubConfigurationKey 'InternalConfigKeys' $fileName = Get-PowerStubConfigurationKey 'ConfigFile' # Ensure config directory exists $configDir = Split-Path $fileName -Parent if (-not (Test-Path $configDir)) { New-Item -ItemType Directory -Path $configDir -Force | Out-Null } $exportConfig = @{} foreach ($key in $Script:PSTBSettings.Keys) { #do not export values for internal keys if ($noExport -contains $key) { continue } $exportConfig[$key] = $Script:PSTBSettings[$key] } $hashAlgorithm = [System.Security.Cryptography.SHA256]::Create() $pathBytes = [System.Text.Encoding]::UTF8.GetBytes([System.IO.Path]::GetFullPath($fileName).ToUpperInvariant()) $hash = [System.BitConverter]::ToString($hashAlgorithm.ComputeHash($pathBytes)).Replace('-', '') $mutexName = "PowerStubConfig-$hash" $mutex = [System.Threading.Mutex]::new($false, $mutexName) $lockTaken = $false $tempFile = Join-Path $configDir "$([System.IO.Path]::GetFileName($fileName)).$PID.$([guid]::NewGuid()).tmp" try { $lockTaken = $mutex.WaitOne([TimeSpan]::FromSeconds(10)) if (-not $lockTaken) { throw "Timed out waiting to write PowerStub configuration file '$fileName'." } # Atomic write: write to a process-unique temp file, then rename into place. $exportConfig | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $tempFile -Encoding UTF8 Move-Item -LiteralPath $tempFile -Destination $fileName -Force } finally { if (Test-Path -LiteralPath $tempFile) { Remove-Item -LiteralPath $tempFile -Force -ErrorAction SilentlyContinue } if ($lockTaken) { $mutex.ReleaseMutex() } $mutex.Dispose() $hashAlgorithm.Dispose() } } |