I am trying to implement information updates in an XML file, by multiple processes running on multiple machines somewhat concurrently. My thinking is to loop for 10 minutes, trying to open and lock the file for writing at random intervals up to 1 second. Once the file is open and locked, I load all the XML, add information for the current machine, sort the XML then resale and remove the lock, so the next machine can open. The problem is that Get-Content doesn't lock the file, so two machines could load the same XML, rather than the second loading XML with data from the first.
I found this, which provides a way to lock the file, then read by stream, but when I tried modifying to this
$file = [IO.File]::Open($path, 'Open', 'ReadWrite', 'None')
$xml = Get-Content $path
I get an error because the file is locked. It seems that Get-Content doesn't lock the file, but it does respect a lock that is already there.
So, is there a way to lock the file so only the machine locking can read and write?
And perhaps more importantly, is this even the right approach, or is there some other approach to multiple XML access? It seems like this would be a common scenario, so there must be some best practice way to do it, even if there isn't a native cmdlet approach.
FWIW, I have to support back to PowerShell 2.0, which no doubt constrains how I can approach this.
EDIT: Well, it doesn't seem like Read for the third parameter in the [io.file] bit is working.
I now have this
$path = '\PxSupportPx ToolsResourcesjobs.xml'
foreach ($i in 1..10) {
$sleepTime = get-random -minimum:2 -maximum:5
$file = [IO.File]::Open($path, 'Open', 'ReadWrite', 'Read')
[xml]$xml = Get-Content $path
$newNode = $xml.createElement('Item')
$newNode.InnerXml = "$id : $i : $sleepTime : $(Get-Date)"
$xml.DocumentElement.AppendChild($newNode) > $null
$xml.Save($path)
$file.Close()
}
Which in theory should take the XML I have, with two dummy log items, read it, append another log item (with an ID, the iteration, the sleep time and the time stamp) and repeat 10 times, with random sleeps between. It poops the bed trying to save with
"The process cannot access the file '\PxSupportPx ToolsResourcesjobs.xml' because it is being used by another process."
Am I really trying to do something that hasn't been done 1000 times before?
OK, based on what comments, here is where I am at. I want to make sure the original cannot be (easily) edited manually while processing is going on. So I have implemented this.
1: Look for a sentinel file and if not found
2: Lock the original file so it can't be modified
3: Copy the original to be the sentinel file
4: Modify the sentinel file as needed
5: Unlock the original
6: Copy the sentinel file over the original
7: Delete the sentinel
Seems to me the iffy bit is just if someone manually modifies the original between unlocking it and the sentinel getting copied, which is highly unlikely. But, it seems like there should be a way to handle this with 100% certainty, and I can't think of a way with or without sentinel files.
See Question&Answers more detail:
os