0

I have a log file that is open and in use by another program, and I read it's contents with the following:

    Dim strContents As String
    Dim x As New FileStream(FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
    Dim objReader As StreamReader
    objReader = New StreamReader(x)
    strContents = objReader.ReadToEnd()
    objReader.Close()

This works for reading the text from the file while it is still in use by the other program, however, immediately after this I need to truncate the text file (without deleting it) so that it is blank again. But the file will still be in use by the other program.

I tried

    Dim sWrite As StreamWriter
    sWrite = New System.IO.StreamWriter(FullPath, False)
    sWrite.Write("")
    sWrite.Close()

But I get the "in use by another application" exception. I've tried looking in StackOverflow and googling but I can't seem to find an answer, and I can't find a way to do this with filestreams either, or I would try to use

Dim fs As New FileStream(FullPath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)

Thanks in advance.

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
Frustrated Guy
  • 669
  • 1
  • 8
  • 10

4 Answers4

1

Thats because the other program has a lock on the file the operating system won't let you do what you want to do. Unless you change the other program to no lock on write.

rerun
  • 25,014
  • 6
  • 48
  • 78
1

There are a fair few other posts on this topic.

Detecting whether a file is locked by another process (or indeed the same process)

How to check for file lock?

Can I simply 'read' a file that is in use?

The solution appears to be:

Try
'Code to read file if its not locked by another app
Catch as System.IO.IOException

Also just an FYI that your log file is unmanaged resource so deterministic finalization will help with this resource contention issue. Use the Using statement for deterministic finalization, eg:

Using fs = New FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
    fs.SetLength(0)
    file.Save(fs)
    fs.Flush()
End Using
Community
  • 1
  • 1
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • I have a scheduled process that writes to a log file. If someone logs into the server and leaves file explorer up, with that log file selected, the scheduled process gets this exception and either fails to run, or can't write to its log file. So annoying. File explorer should open the file, display the preview, and close it; but no, it holds the file open as long as the file is selected. I can't kill file explorer from the scheduled process, doing that creates a bad problem. – Shavais Mar 12 '14 at 15:56
0

Unfortunately, the solution to the problem is not as simple adding or modifying a few lines code, regardless of the language being used. You are describing a classic example of resource contention.

This type of problem is best solved using an access manager, i.e. another process that arbitrates writes such that your program doesn't overwrite what the other program did and vice versa.

Android Eve
  • 14,864
  • 26
  • 71
  • 96
  • The program that is logging only actually writes data every 3-5 minutes, I'm trying to clear the data from the log in between those writes, it's only complicated by the fact that the program doing the logging doesn't release it's lock on the text file in between writes. I'm okay with the concept that if I clear it in the middle of writing I would end up with weird data. – Frustrated Guy Dec 10 '10 at 00:56
  • Do you have control over the **other** program? If you can modify it in any way *and* guarantee synchronization between the two programs, make it Close() the file after each write. – Android Eve Dec 10 '10 at 03:24
  • Negative, I have no control over the other program. – Frustrated Guy Dec 10 '10 at 03:45
  • Ouch! You must use the Event Logging API then. See http://www.codeproject.com/KB/cs/WriteEventLog.aspx – Android Eve Dec 10 '10 at 05:24
0

I'm not sure if you can do that until the other process closes the stream. However, you can kill the process that is writing to the file.

Here's an example to do that.

Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName("notepad")

For Each p As Process In pProcess
    p.Kill()
Next

Check this out: http://vbnetsample.blogspot.com/2007/08/start-and-kill-process.html

Arash N
  • 324
  • 1
  • 2
  • 10