Private/Invoke-WithFileLock.ps1
|
function Invoke-WithFileLock { <# .SYNOPSIS Acquires a file-based lock, runs a script block, then releases the lock. On contention, warns the user, waits 10 seconds, and retries once before failing. .PARAMETER LockFile Full path of the lock file to create. .PARAMETER ScriptBlock Code to run while the lock is held. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$LockFile, [Parameter(Mandatory)] [scriptblock]$ScriptBlock ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' function _TryAcquire { if (-not (Test-Path $LockFile)) { "$PID $(Get-Date -Format 'o')" | Set-Content -Path $LockFile -Encoding UTF8 -NoNewline return $true } return $false } if (-not (_TryAcquire)) { $info = Get-Content $LockFile -Raw -ErrorAction SilentlyContinue Write-Warning "[Lock] Another Invoke-CpmfUipsPack is running ($info). Waiting 10 seconds before retrying..." Start-Sleep -Seconds 10 if (-not (_TryAcquire)) { throw "Lock file still present at '$LockFile'. If no other process is running, delete it manually." } } try { & $ScriptBlock } finally { Remove-Item $LockFile -Force -ErrorAction SilentlyContinue } } |