Scripts/WriteNFSv3ExtendedGroupsLog.ps1

function Write-NFSv3ExtendedGroupsLog {
    param (
        [string]$Message,
        [string]$LogLevel = "INFO",
        [string]$LogFile = $Global:NFSv3ExtendedGroupsLogFile,
        
        [Parameter(Mandatory = $false)]
        [ValidateSet('SilentlyContinue', 'Continue', 'Inquire', 'Stop', 'Suspend')]
        [string]$VerbosePreference
    )

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"
    $logEntry = "[$timestamp] [$PID] [$LogLevel] $Message"

    if ($LogLevel -eq "ERROR") {
        Write-Error $Message
    } elseif ($LogLevel -eq "WARNING") {
        Write-Warning $Message
    }

    if ($VerbosePreference -eq 'Continue') {
        Write-Verbose $Message
    }
    
    # Take lock on the file so that only one process can update it at time.
    $mutex = New-Object System.Threading.Mutex $false, "Global\MyLogMutex"
    $retryInterval = 500
    $maxRetry = 5
    $retryCount = 0
    $isSuccess = $false
    
    try {
        # Wait indefinitely to acquire the mutex.
        $mutex.WaitOne() | Out-Null

        while ($isSuccess -eq $false -and $retryCount -le $maxRetry) {
            try {
                # Open the file with exclusive access (file locking) using FileShare::None.
                $fileStream = [System.IO.File]::Open($LogFile, [System.IO.FileMode]::Append, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None)
                
                # Use a StreamWriter to write the log entry.
                $writer = New-Object System.IO.StreamWriter($fileStream)
                $writer.WriteLine("$logEntry")
                $writer.Flush()

                # Close the StreamWriter and the FileStream.
                $writer.Close()
                $fileStream.Close()

                $isSuccess = $true
            } catch {
                # Increase retryCount and wait for 0.5 seconds to again open file.
                Write-Warning "$_, retrying..."
                $retryCount += 1
                Start-Sleep -Milliseconds $retryInterval
            }
        }

        # Release mutex once log has been written to file.
        $mutex.ReleaseMutex() | Out-Null
    } catch {
        Write-Error "Error while writing logs: $_" 
    } finally {
        $mutex.Dispose() | Out-Null
    }
}