¿El bloc de notas los supera a todos?

134

En un sistema Windows Server 2012 R2, un programa Kotlin usa FileChannel.tryLock()para mantener un bloqueo exclusivo en un archivo, como este:

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

Con este bloqueo en su lugar, no puedo abrir el archivo con:

  • WordPad
  • Notepad ++
  • Programáticamente con C #, para cualquier valor de FileShare:

    using (var fileStream = new FileStream(processIdPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (var textReader = new StreamReader(fileStream))
    {
        textReader.ReadToEnd();
    }
    
  • Desde la línea de comando, el typecomando:

    C:\some-directory>type file.txt
    The process cannot access the file because another process has locked a portion of the file.
    
  • Internet Explorer (sí, estaba desesperado)

Yo puedo abrirlo con el Bloc de notas.

¿Cómo diablos es que el Bloc de notas puede abrir un archivo bloqueado que nada más puede?

Monohilo
fuente

Respuestas:

202

El Bloc de notas lee los archivos asignándolos primero a la memoria, en lugar de utilizar los mecanismos de lectura de archivos "habituales" presumiblemente utilizados por los otros editores que intentó. Este método permite la lectura de archivos incluso si tienen bloqueos exclusivos basados ​​en rangos.

Puede lograr lo mismo en C # con algo similar a:

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);
}
Iridio
fuente
58
Confirmado con más detalle por Raymond Chen de Microsoft : para cargar un archivo, el Bloc de notas asigna una vista del archivo como un archivo asignado en memoria y lo utiliza como fuente. El código calcula la codificación, realiza una conversión de página de códigos a UTF-16LE si es necesario, coloca el resultado en un bloque de memoria y luego usa el mensaje EM_SETHANDLE para entregar todo el bloque al control de edición.
Stevoisiak