145

On a Windows Server 2012 R2 system, a Kotlin program uses FileChannel.tryLock() to hold an exclusive lock on a file, like this:

val fileRw = RandomAccessFile(file, "rw")
fileRw.channel.tryLock()

With this lock in place, I cannot open the file with:

  • WordPad
  • Notepad++
  • Programmatically with C#, for any value of FileShare:

    using (var fileStream = new FileStream(processIdPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (var textReader = new StreamReader(fileStream))
    {
        textReader.ReadToEnd();
    }
    
  • From the command line, the type command:

    C:\some-directory>type file.txt
    The process cannot access the file because another process has locked a portion of the file.
    
  • Internet Explorer (yes, I was desperate)

I can open it with Notepad.

How the heck is Notepad able to open a locked file that nothing else can?

MonoThreaded
  • 11,429
  • 12
  • 71
  • 102

1 Answers1

213

Notepad reads files by first mapping them into memory, rather than using the "usual" file reading mechanisms presumably used by the other editors you tried. This method allows reading of files even if they have an exclusive range-based locks.

You can achieve the same in C# with something along the lines of:

using (var f = new FileStream(processIdPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var m = MemoryMappedFile.CreateFromFile(f, null, 0, MemoryMappedFileAccess.Read, null, HandleInheritability.None, true))
using (var s = m.CreateViewStream(0, 0, MemoryMappedFileAccess.Read))
using (var r = new StreamReader(s))
{
    var l = r.ReadToEnd();
    Console.WriteLine(l);
}
MultiplyByZer0
  • 6,302
  • 3
  • 32
  • 48
Iridium
  • 23,323
  • 6
  • 52
  • 74
  • 64
    Confirmed in more detail by [Microsoft’s Raymond Chen](https://blogs.msdn.microsoft.com/oldnewthing/20180521-00/?p=98795): *To load a file, Notepad maps a view of the file as a memory-mapped file and uses that as the source. The code figures out the encoding, performs a code page conversion to UTF-16LE if necessary, puts the result in a memory block, and then uses the EM_SET­HANDLE message to hand that entire block to the edit control.* – Stevoisiak May 22 '18 at 13:50
  • 7
    That blog post got moved slightly; it's now at https://devblogs.microsoft.com/oldnewthing/20180521-00/?p=98795 (the domain name changed) – SamB May 19 '22 at 00:22
  • Interestingly, when I try to open a locked file in c# this way, it throws an exception on the constructor of the first `FileStream`, or if I use the overload of `MemoryMappedFile.CreateFromFile` which accepts a filename, it throw the same exception (*"The process can not access the file because it is in use by another process"*). The `type` command however, and of course, Notepad, do succeed. – Rotem Jun 28 '22 at 17:59