Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File.Open for read access denied on executing file in Windows

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

like image 992
Vegar Westerlund Avatar asked Aug 10 '11 08:08

Vegar Westerlund


2 Answers

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
}
like image 168
lowds Avatar answered Oct 04 '22 20:10

lowds


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. :)

like image 26
Skomski Avatar answered Oct 04 '22 19:10

Skomski