Dealing With File Locks

Sometimes, when you try and access a file, it may refuse to open because it is locked by another user or process. Likewise, you may want to lock a file yourself to make sure the file is not accessed and read/changed while you are manipulating it. Which raises the question: how do you control file locks?

Locking a file

Get-Content can read text-based files. This cmdlet is not locking the file, so while you are reading it, others can still access or even change it.

To apply a file lock, you need to use low level .NET methods. The next example illustrates how to open a file with a read/write lock. While this script is running, no one can access the file:

$file = [System.io.File]::Open('c:\files\somefile.txt', 'Open', 'Read', 'None')
Read-Host 'Press ENTER to release file'
$file.Close()

The method Open() accepts four arguments:

  • The path to the file you want to access
  • The action you want to take, for example "Open"
  • The access you want to use, for example "Read"
  • The lock. "None" grants to access to others, so the file is locked. "Read" would allow others to read the file while you are using it, and "ReadWrite" would allow others to read and/or write to the file while you are using it

Reading File Content

When you lock a file, no one else can access it, so you cannot use Get-Content to read its content anymore, either. To read the file content, you would have to refer to .NET methods. Here is an example that reads file content of a file you applied a lock on:

$file = [System.io.File]::Open('c:\files\somefile.txt', 'Open', 'Read', 'None')
$reader = New-Object System.IO.StreamReader($file)
$text = $reader.ReadToEnd()
$reader.Close()
$file.Close()

Dealing With Existing File Locks

When you try and access a file, others may have already applied locks to it. For example, windows maintains a file called $env:windir\windowsupdate.log which carries a "Write" lock: you can read its contents, but you cannot write to it.

If you tried and accessed that file with a lock of type "None" (exclusive access), your code would fail because the system already implemented a lock which is incompatible to the lock you wanted to apply. You can only lock a file for exclusive access if noone else has applied a lock before.

To deal with this, you would have to make sure your lock is not conflicting with existing locks. When you specify a "ReadWrite" lock (essentially allowing others to still read and write the file), you can safely read the file despite other locks (except if someone had applied a "None" lock):

$file = [System.io.File]::Open("$env:windir\windowsupdate.log", 'Open', 'Read', 'ReadWrite')
$reader = New-Object System.IO.StreamReader($file)
$text = $reader.ReadToEnd()
$reader.Close()
$file.Close()

This is how Get-Content works. It uses a "ReadWrite" lock. The above low level .NET access is a lot faster though because it is not reading the file line by line. Instead, it returns the entire file content as one (large) string.

Hope to see you next week,

Tobias

Microsoft MVP PowerShell Germany

P.S.
If you live in Germany or other parts of Europe and your company would like to set up a truly great PowerShell training, just contact me! I regularly train mid- to large-size companies. Trainings are always a blast with tons of real-world-examples and solutions. Here's how to get in touch with me: tobias.weltner@scriptinternals.de 

 


Posted Jun 23 2011, 01:40 PM by Tobias
Filed under: , , , ,
Copyright 2012 PowerShell.com. All rights reserved.