FileStream with locked file - c#

I am wondering if it's possible to get a readonly FileStream to a locked file?
I now get an exception when I try to read the locked file.
using (FileStream stream = new FileStream("path", FileMode.Open))
Thanks!

You should try another constructor. They are documented at MSDN.
This one looks like a bet:
FileStream Constructor (String, FileMode, FileAccess, FileShare)
MSDN Link
FileAccess
A constant that determines how the file can be accessed by the FileStream object. This gets the CanRead and CanWrite properties of the FileStream object. CanSeek is true if path specifies a disk file.
FileShare
A constant that determines how the file will be shared by processes.

using (FileStream stream = new FileStream("path", FileMode.Open))
That will use the default value for the FileShare argument, FileShare.Read. Which denies any process from writing to the file. That cannot work if another process is writing to the file, you cannot deny a right that was already gained.
You have to specify FileShare.ReadWrite. That might still not work if the other process used FileShare.None, no workaround for that. Beware that getting read access to a file that's being written is troublesome, you don't have a reliable end-of-file indication. The last record or line in the file might have only been partially written.

I've used the following which works, however should use with caution as file can be modified while you have it open by another process.
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read,FileShare.ReadWrite);

You can simply unlock file and read file after it.
Just use Handle.exe from Sysinternals , or Unlocker with command line options.
They both can unlock file , and you can execute them from your program easily,
without leaving your program.
(But don't use them for Windows SAM file, it doesn't work with SAM ;) )
Good luck !

Related

File can´t rewritten because other process uses the file

I´ve written some code to send files as attachments of .eml files with C#.
I create the files in an Windows temp folder and attach them to a .eml file.
The .eml files are simply opened and send through Process.Start(filename); with the standard mailing program in windows. If the users wishes to send the file again, the file will be rewritten from the database to make sure its the newest version. Now to my problem: Randomly a few times or after just the first time I rewrite the file the error appears
The process cannot access the file because it is being used by another process
I acutally did some research on the web and found this other question. So I made sure like mentioned there, that the FileStream is set correctly with all arguments.var fs = new FileStream(tempPathSave, FileMode.Open, FileAccess.Write, FileShare.ReadWrite) Has someone an idea what is the reason for my problem? My biggest problem is, that I can´t really duplicate it to say it is happening when I do this or that.
EDIT: I am using the FileStream in an using statement to make sure that it is disposed right.
It is hard to properly understand what the problem is without actually seeing the code but from my experience you are not properly disposing the filestream object so it keeps a handle to the file
var fs = new FileStream(tempPathSave, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)
So when you are done using your filestream, call
fs.Dispose();
which will dispose your filestream properly.
Moreover, you can use syntatic sugar, using which will automatically dispose your object
using(var fs = new FileStream(tempPathSave, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)){
// use fs here
// STUFF
} //at the end fs will be disposed
I´ve found a solution for my problem. I just changed the FileStream to MemoryStream because the MailMessage constructor can handle a stream, too. The only point there is, that you have to keep the MemoryStream open until the .eml file is saved. And more important you have to watch out about the memory usage und make sure the afterwards every MemoryStream will be disposed.

Opening and reading a file which is open in Excel

It is possible to use a FileShare value of FileShare.ReadWrite to open a file for reading, while it is already open in other programs (e.g. like Excel). e.g.:
using (FileStream fs = new FileStream(#"c:\abd\somefile.xlsx",
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// read file, etc.
}
Just wondering if this a good idea. e.g. in worst case, what will happen if the external program is writing to the file, and your code is trying to read it at the same time ?
I have noticed libraries like spreadsheet gear that can read files even when they are open in Excel - are they basically hoping that they will be able to read the whole file into memory before any part of it is changed ?

Prevent a user from deleting, moving or renaming a file

What I am trying to do is while my program is using a file, I want to keep the user from renaming, deleting, or moving the file (well... a move is a delete and a create at a different location according to Windows FileSystemWatcher, but I digress).
It has been suggested that I use FileStream.Lock or use a Mutex. However, FileStream.Lock seems only to prevent the file from being modified which I am trying to allow. Also, I am very unsure as to if a mutex can lock a file, although I am still reading on it with in the .Net 4.0 library.
Does anyone have any advice on utilizing either one and if there is a code based solution to this problem?
When you are opening the file, you can specify the sharing mode.
Opening the file with FileAccess.Read gives you the ability to read the file, while FileShare.ReadWrite allows the file to continue to be edited, but not deleted or moved.
var fs = File.Open(#"C:\temp\file.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
MessageBox.Show("File Locked"); // While the messagebox is up, try to open or delete the file.
// Do your work here
fs.Close();
This will prevent moving or deleting the file but allows read and write:
using (FileStream fs = new FileStream(#"C:\TestDir\Test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// Do Stuff.
}
FileStream.Lock is actually a range lock which prevents modification of a particular portion of a file while the lock is held.

when using FileStream to open a file, I am wondering whether or not the file will be locked?

I am wondering in which case .Net will lock the file when one use FileStream or similar mechanism?
Not sure what you mean by "lock the file", but when stream initialized using:
FileShare = None - Declines sharing of the current file. Any request to open the file (by this process or another process) will fail until the file is closed.
Check out MSDN FileShare Enumeration page which contains a detailed description for each share mode.
You can specify that yourself:
var file = new FileStream("C:\\file.txt", FileMode.Open, FileAccess.Read)
if you use FileAccess.Read it will stay unlocked, with Write or ReadWrite it will be locked.

How can I lock a file while writing to it via a FileStream?

I am trying to figure out how to write a binary file with a FileStream and BinaryWriter, and keep the file locked for read while I am writing. I specifically don't want other applications/processes to be able to read from the while while its being written to.
//code to declare ba as a byte array
//dpath is the path to the file
FileStream BinaryFile = new FileStream(dpath, FileMode.Create, FileAccess.Write);
BinaryWriter Writer = new BinaryWriter(BinaryFile);
Writer.Write(ba);
Writer.Close();
BinaryFile.Dispose();
Now the problem is the file can be opened by other applications during the write, which is undesirable in my current application. The FileStream has a Lock Method, but that locks for writing and not for reading, so that doesn't help me.
You're looking for the fourth parameter of the FileStream Constructor.
public FileStream(
string path,
FileMode mode,
FileAccess access,
FileShare share
)
So in your case:
FileStream BinaryFile = new FileStream(dpath, FileMode.Create,
FileAccess.Write, FileShare.None);
FileShare-Enum:
Contains constants for controlling the kind of access other FileStream
objects can have to the same file.
Members:
None, Declines sharing of the current file. Any request to open the file (by this process or another process) will fail until the file is closed.
Read, Allows subsequent opening of the file for reading. If this flag is not specified, any request to open the file for reading (by this process or another process) will fail until the file is closed. However, even if this flag is specified, additional permissions might still be needed to access the file.
Write, Allows subsequent opening of the file for writing. If this flag is not specified, any request to open the file for writing (by this process or another process) will fail until the file is closed. However, even if this flag is specified, additional permissions might still be needed to access the file.
ReadWrite, Allows subsequent opening of the file for reading or writing. If this flag is not specified, any request to open the file for reading or writing (by this process or another process) will fail until the file is closed. However, even if this flag is specified, additional permissions might still be needed to access the file.
Delete, Allows subsequent deleting of a file.
Inheritable, Makes the file handle inheritable by child processes. This is not directly supported by Win32.
I don't know if it is possible.
For instance Firefox stores files while downloading using another name until they are finished. When everything is there, it renames it to the original name. A different file suffix will avoid that users try to open it with a double click.

Categories