Get-Content -Wait is locking the file while it reads it, preventing Add-Content from writing data

4.4k views Asked by At

I'm using powershell to write and read log files.

One script is generating a log file with Add-Content. Another script is tailing the log file, using Get-Content -Wait. This seems like it should be pretty reliable.

However, the writer is frequently unable to write, and the reader is frequently unable to read and gives up. I can only assume these two commands aren't opening the file with the appropriate access flags, and so they're fighting each other.

Here's a nasty little script that demonstrates the problem with two jobs in the same process, although the same happens between different powershell processes:

$writer = start-job -ScriptBlock {     
    foreach($i in 1..500)
    {
        "$i" | Add-Content "c:\temp\blah.txt"
        Sleep -Milliseconds 10
    }
}

$reader = start-job -ScriptBlock { 
    Get-Content "c:\temp\blah.txt" -wait
}

while($writer.State -eq "Running")
{
    Sleep 1
}
Sleep 2

"Checking writer"
receive-job $writer

"Checking reader"
receive-job $reader

remove-job $writer -force
remove-job $reader -force

On my Windows 7 x64 machine with powershell 3 ISE, I typically get lots of write errors:

Checking writer
The process cannot access the file 'C:\temp\blah.txt' because it is being used by another process.
    + CategoryInfo          : ReadError: (C:\temp\blah.txt:String) [Get-Content], IOException
    + FullyQualifiedErrorId : GetContentReaderIOError,Microsoft.PowerShell.Commands.GetContentCommand
    + PSComputerName        : localhost

And then the file being read has gaps in it:

Checking reader
...
23
24
25
54
55
56
...

NB this is a different problem to the one discussed here: Get-Content -wait not working as described in the documentation and here: https://social.technet.microsoft.com/Forums/windowsserver/en-US/e8ed4036-d822-43d3-9ee5-dd03df3d9bfc/why-doesnt-wait-work-and-why-doesnt-anyone-seem-to-care?forum=winserverpowershell which are about tailing a file which isn't being closed in between writes.

Is there any way of using Get-Content and Add-Content like this, or should I give up, and use something else to read and write my log files?

1

There are 1 answers

4
campbell.rw On BEST ANSWER

Try using Out-File instead of Add-Content

Replace

Add-Content "c:\temp\blah.txt"

With:

Out-File "c:\temp\blah.txt" -Append -Encoding ascii

You need to specify encoding as ascii with Out-File if that's what you want, since it's the default for add-content but not the default for out-file. You also need to to use -append and/or -noclobber to avoid overwriting existing file content.