File Lock Mechanism using PowerShell

Issue

I have two processes that reads from the same file. I want to make sure that those two processes doesn’t run at the same. My approach is that , when a process starts, it should look for a file(process.txt). If the file doesn’t exist, it creates the file and continue execution, reading from the shared file(sharedfile.txt) between the two processes. It then deletes the process.txt file after executing.

Since both process deletes process.txt file after execution, if the file exists,it should go into a start sleep until the other process finishes and deletes the file.

The problem here is when one process finishes and deletes the file(process.txt), the other still stay in the loop without executing even if no file exists. I am not sure of the right loop to use. I tried a couple of them and couldn’t achieve my goal.

Clear Host
$sleeptime = 15
$lockfile = "C:\Users\processid.txt"
$file = test-path -Path $lockfile
Try
{
if($file -eq 'True')
{
echo “Lock file found!”
echo "This means file is being used by another process"
echo "Wait for file to be deleted/released"
echo “Sleeping for $sleeptime seconds”
Start-Sleep $sleeptime -Verbose
}
else
{
    New-item -Path $lockfile
    #Executing a code here
}
    Remove-Item $lockfile –Force
}
}
Catch
{
Write-Host $_.Exception.Message`n
}

Solution

Consider this one, it creates a lock file and opens it for exclusive access. Let’s you run your script, then cleans up afterwards. If access cannot be gained it waits 5 seconds before trying again.

Using this for both scripts should make them play nice and wait for their turn. If for some reason a lock file gets left behind (unplanned reboot that aborts script or similar) this one will still work fine as well.

$LockFile = 'C:\temp\test.lock'

# Loop that runs until we have exclusive write access to $LockFile
while ($FileStream.CanWrite -eq $false) {
    if (-not (Test-Path -Path $LockFile)) {
        Set-Content -Path $LockFile -Value 'Lockfile'
    }
    try {
        $FileStream = [System.IO.File]::Open("C:\temp\test.lock",'Open','Write')
    }
    catch {
        'Waiting 5 seconds'
        Start-Sleep -Seconds 5
    }
}

# ---
# Your actual script here
# ---

# Cleanup
$FileStream.Close()
$FileStream.Dispose()
Remove-Item -Path $LockFile -Force

You could also go one step further and instead lock the file you’re actually using, but then you’ll need to read it from the file stream since it will be locked for any cmdlets.

Answered By – PMental

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published