Question

I have a problem with file permissions on executing files in Windows that seems to be solved after following a forum tip[1], but I cannot understand why. Maybe you guys can help.

I'm checking the banner of a file by executing it (reading the console output) and then opening the same file for reading afterwards using FileStream:

public void fileMD5(string filename) {
  if (!File.Exists(filename)) return NT.Fail("File does not exist: " + filename);

  BinaryReader stream = new BinaryReader(File.Open(filename,
      FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
  int bufferSize = 4096;
  byte[] buffer = new byte[bufferSize];
  int readBytes;
  while ((readBytes = stream.Read(buffer, 0, bufferSize)) > 0) {
    md5Hasher.TransformBlock(buffer, 0, readBytes, buffer, 0);
  }
  stream.Close();
}

fileMD5('sample.exe');

and every once in a while I would get "file is being used by another process". From Wikipedia I know that Windows will set a lock on executing files denying write access[2], but I'm only reading. Also the process should have stopped already when I try to open it.

From the forum post it would seem that adding a FileShare.ReadWrite would help and it seems that It does:

FileStream stream = File.Open('sample.exe', 
    FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

But I don't understand why. Is there a race condition here that I don't see?

Also the File.Open call seems to be much quicker with FileShare.ReadWrite instead of the default (which I guess is FileShare.Read).

[1] http://www.xtremevbtalk.com/archive/index.php/t-192118.html

[2] http://en.wikipedia.org/wiki/File_locking#In_Microsoft_Windows

Was it helpful?

Solution

When you do not specify a FileShare parameter the default for this option is FileShare.None, in fact the code within the File class simply executes this:

public static FileStream Open(string path, FileMode mode, FileAccess access)
{
    return File.Open(path, mode, access, FileShare.None);
}

With regards to the performance I can only imagine that specifying FileShare.ReadWrite means that Windows does not need to aquire a lock on the file.

As far as the "file is being used by another process" error you are getting does this issue go away if you wrap the usage of the stream variable within a using block so that the Stream gets disposed of as soon as you are done?

using (var stream = File.Open('sample.exe', FileMode.Open, FileAccess.Read))
{
  //do something with the stream here
}

OTHER TIPS

You should close your FileStream and then afterwards open a new FileStream.

FileShare is needed when applications want to share a file not only one application or an application has multiple readers or writers at the same time.

Why? It's get messy when everyone can read and write at the same time. In this case you should better explicitly set it so its clear that its get messy. :)

It has to do with the underlying windows API CreateFile flags. See http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx for an overview, http://blogs.msdn.com/b/larryosterman/archive/2004/05/13/131263.aspx for en explanation on how NT (and following) load the execs with FILE_SHARE_DELETE

And especially this

http://blogs.msdn.com/b/oldnewthing/archive/2004/05/11/129759.aspx

For a great explanation on how the share permission and desired access compose together!

It seems like specifying the wrong FileShare can prohibit you from accessing a file. If you specify FileShare.Read but some other application has currently write access to that file, you cannot access the file, since your FileShare.Read is currently not satisfiable. FileShare.ReadWrite is less restrictive, because its easier satisfiable. Source: http://blogs.msdn.com/b/oldnewthing/archive/2004/05/11/129759.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top