What's the least invasive way to read a locked file in C# (perhaps in unsafe mode)?
Asked Answered
M

3

43

I need to read a Windows file that may be locked, but I don't want to create any kind lock that will prevent other processes from writing to the file.

In addition, even if the file is locked for exclusive use, I'd like to see what's inside.

Although this isn't my exact use case, consider how to read a SQL/Exchange log or database file while it's in use and mounted. I don't want to cause corruption but I still want to see the insides of the file and read it.

Medawar answered 24/8, 2010 at 20:14 Comment(0)
D
18

The accepted answer is not correct. If the file is really locked, you cannot just change the file share. This would work if the lock has been set with this fileshare option too but it does not mean that it is the case. In fact, you can test @CaffGeek solution pretty easily by opening the file without the FileShare.ReadWrite and than trying to open it with this flag to ReadWrite. You will get that the file is using by another process.

Code:

string content;
var filePath = "e:\\test.txt";

//Lock Exclusively the file
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);

//CaffGeek solution
using (FileStream fileStream = new FileStream(
        filePath,
        FileMode.Open,
        FileAccess.Read,
        FileShare.ReadWrite))
{
    using (StreamReader streamReader = new StreamReader(fileStream))
    {
        content = streamReader.ReadToEnd();
    }
}

As you can see, it crashes. This result is the same with any FileStream method like the File.Open. It will crash what ever you put for FileShare during the open stage.

//OPEN FOR WRITE with exclusive
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);


//OPEN FOR READ with file share that allow read and write
var x = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //Crash

Copying the file is not also an option. You can try it your self by opening the file exclusively and try to copy the file on Windows Explorer or by code:

var filePath = "e:\\test.txt";
var filePathCopy = "e:\\test.txt.bck";

//Lock the file
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);

File.Copy(filePath, filePathCopy);
var x = File.Open(filePathCopy, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var reader = new StreamReader(x))
{
    content = reader.ReadToEnd();
}

r.Close();
File.Delete(filePathCopy);

This code crash when you hit the File.Copy line. The exception is the same as before : file is being using by another process.

You need to kill the process that has the lock of the file if you want to read it OR if you have the source code of the file that is locking the file to change this one to use FileShare.ReadWrite instead of just FileShare.Write.

Domineering answered 10/9, 2014 at 15:10 Comment(2)
That or perhaps I can use the backup, VSS APIs somehowMedawar
I actually have success copying the file, but run into lock issues on the copy (some state being copied along?)Rateable
C
56

You can do it without copying the file, see this article:

The trick is to use FileShare.ReadWrite (from the article):

private void LoadFile()
{
    try
    {
        using(FileStream fileStream = new FileStream(
            "logs/myapp.log",
            FileMode.Open,
            FileAccess.Read,
            FileShare.ReadWrite))
        {
            using(StreamReader streamReader = new StreamReader(fileStream))
            {
                this.textBoxLogs.Text = streamReader.ReadToEnd();
            }
        }
    }
    catch(Exception ex)
    {
        MessageBox.Show("Error loading log file: " + ex.Message);
    }
} 
Clanton answered 24/8, 2010 at 20:28 Comment(2)
I just posted a new question in response to seeing this: #3561421Medawar
Thank you very much. It worked for my openvpn log file.Perseverance
D
18

The accepted answer is not correct. If the file is really locked, you cannot just change the file share. This would work if the lock has been set with this fileshare option too but it does not mean that it is the case. In fact, you can test @CaffGeek solution pretty easily by opening the file without the FileShare.ReadWrite and than trying to open it with this flag to ReadWrite. You will get that the file is using by another process.

Code:

string content;
var filePath = "e:\\test.txt";

//Lock Exclusively the file
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);

//CaffGeek solution
using (FileStream fileStream = new FileStream(
        filePath,
        FileMode.Open,
        FileAccess.Read,
        FileShare.ReadWrite))
{
    using (StreamReader streamReader = new StreamReader(fileStream))
    {
        content = streamReader.ReadToEnd();
    }
}

As you can see, it crashes. This result is the same with any FileStream method like the File.Open. It will crash what ever you put for FileShare during the open stage.

//OPEN FOR WRITE with exclusive
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);


//OPEN FOR READ with file share that allow read and write
var x = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); //Crash

Copying the file is not also an option. You can try it your self by opening the file exclusively and try to copy the file on Windows Explorer or by code:

var filePath = "e:\\test.txt";
var filePathCopy = "e:\\test.txt.bck";

//Lock the file
var r = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.Write);

File.Copy(filePath, filePathCopy);
var x = File.Open(filePathCopy, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (var reader = new StreamReader(x))
{
    content = reader.ReadToEnd();
}

r.Close();
File.Delete(filePathCopy);

This code crash when you hit the File.Copy line. The exception is the same as before : file is being using by another process.

You need to kill the process that has the lock of the file if you want to read it OR if you have the source code of the file that is locking the file to change this one to use FileShare.ReadWrite instead of just FileShare.Write.

Domineering answered 10/9, 2014 at 15:10 Comment(2)
That or perhaps I can use the backup, VSS APIs somehowMedawar
I actually have success copying the file, but run into lock issues on the copy (some state being copied along?)Rateable
O
1

You can probably create a copy and read that, even if the file is locked.

Or maybe a StreamReader on a FileStream depending on how SQL opened the file?

new FileStream("c:\myfile.ext", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Ockham answered 24/8, 2010 at 20:16 Comment(1)
That could work... but a database is big. Maybe I need to know how Copy works, since I want that type of access.Medawar

© 2022 - 2024 — McMap. All rights reserved.