4

Here's what I have in mind:

        var file = @"myfile";
        File.Open(file,
                  FileMode.Open, FileAccess.ReadWrite, FileShare.None);

        using (StreamReader rdr = new StreamReader(File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)))
        {
            rdr.ReadToEnd();
        }
        var t = File.ReadAllBytes(file);

Neigther File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read) nor File.ReadAllBytes can read file data.

From my old c++ and winapi days, I do remember, that there used to be a good way to read locked files, if you have backup priviledges, but I have no idea how obtain and use those in c#.

Can anyone provide me with a sample on how to read a file after it has been locked?

Arsen Zahray
  • 24,367
  • 48
  • 131
  • 224
  • If it's locked you're not supposed to be able to read it. That's kinda the point of a lock. – Servy Jun 20 '12 at 15:45
  • the lock in question is done by an other process. I'm going to use this in updater, to check whether files in question need replacement or not (e.g. if the process updated needs a restart) – Arsen Zahray Jun 20 '12 at 15:52
  • 1
    "FileShare.None" is a total lock, so trying to read from it will not work. Original open has to at least allow "FileShare.Read" – Quintium Jun 20 '12 at 15:57

2 Answers2

6

Well, if the file is totally locked (no sharing) you will not be able to read it. If the file was opened to share read, you will be able to read using a non intrusive method:

string fileName = @"myfile";
using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (StreamReader fileReader = new StreamReader(fileStream ))
{
    while (!fileReader .EndOfStream)
    {
        string line = fileReader .ReadLine();
        // Your code here
    }
}
Daniel Peñalba
  • 30,507
  • 32
  • 137
  • 219
  • So, I'm afraid that the file is totally locked by other process. You can use ProcessExplorer (http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx) to see which process is locking the file. – Daniel Peñalba Jun 20 '12 at 15:57
1

What I was trying to do in fact is impossible, and backup privilege doesn't help either:

       [DllImport("kernel32.dll", CharSet = CharSet.Auto,
        CallingConvention = CallingConvention.StdCall,
        SetLastError = true)]
            public static extern SafeFileHandle CreateFile(
                string lpFileName,
                uint dwDesiredAccess,
                uint dwShareMode,
                IntPtr SecurityAttributes,
                uint dwCreationDisposition,
                uint dwFlagsAndAttributes,
                IntPtr hTemplateFile
            );

    private static uint READ_CONTROL = 0x00020000;
    private static uint OPEN_EXISTING = 3;
    private static uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;


        var file = @"myfile";
        File.Open(file,
                  FileMode.Open, FileAccess.ReadWrite, FileShare.None);

        using(PrivilegeEnabler pe = new PrivilegeEnabler(Process.GetCurrentProcess(), Privilege.Backup))
        {
            var hFile = CreateFile(file,           // lpFileName
                       READ_CONTROL,               // dwDesiredAccess
                       0,                          // dwShareMode
                       IntPtr.Zero,                // lpSecurityAttributes
                       OPEN_EXISTING,              // dwCreationDisposition
                       FILE_FLAG_BACKUP_SEMANTICS, // dwFlagsAndAttributes
                       IntPtr.Zero);               // hTemplateFile
            using (var fs=new  FileStream(hFile.DangerousGetHandle(),FileAccess.Read))
            {
                using (StreamReader rdr=new StreamReader(fs))
                {
                    rdr.ReadToEnd();
                }
            }
        }

will still result in an error.

Arsen Zahray
  • 24,367
  • 48
  • 131
  • 224