C# How to lock Access file & work with it? - c#

In my application, one user at a time is supposed to work with an Access DB file for the entire "session" (time span he has the application open). The file shall be locked while one user is working with it.
I do so by using lock according to:
How to lock a file with C#?
FileStream s2 = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.None);
However when accessing the file via code, an exception is thrown, e.g.:
// Connection points to file locked before
using (OleDbConnection connection = new OleDbConnection(Connection)) {
connection.Open();
//...
System.Data.OleDb.OleDbException File is already being used
How to access previously locked file? Do I always have to remove the lock before accessing it? If so, how to ensure the file is not being accessed inbetween unlocking, accessing and relocking?

I think your connection must be Exclusive: http://www.connectionstrings.com/access/

The solution is indeed to create a separate lock file and lock this using a file stream.
(The answer is actually given by Sinatr, just for the sake of completeness I want to share it. Yet to find out is what MS Office does to its office files, as that is the exact behavior I'd like to have - but that is a different question.)

Related

FileStream.close() does not free file for other processes

I have Following Code in a Page_Load called function. When the Page is loaded the first time after starting Visual Studio, everything works out fine.
But any other opening call to the File after that returns IOException: "File is in use by another process", even when directly opening the File in VisualStudio Solution this Error is returned(of course not as Exception)
FileStream mailinglist_FileStream = new FileStream(#"\foobarFile.txt", FileMode.Open);
PeekingStreamReader mailinglist_Reader = new PeekingStreamReader(mailinglist_FileStream);
//Do some stuff with the file
mailinglist_FileStream.Close();
mailinglist_Reader.Close();
mailinglist_Reader.Dispose();
mailinglist_FileStream.Dispose();
Why is the file still locked? and why does fully restarting Visual Studio reset the File?
when checking file-Properties it says:
Build Action: Content
Copy to output directory: do not Copy
I am only reading this File. can i do something similiar to adLockOptimistic, so that multiple processes can access the File?
Why is the file still locked? and why does fully restarting Visual
Studio reset the File? when checking file-Properties it says [...]
I don't know why the file is still locked: probably because your code fails before the stream is closed/disposed.
About "why fully restarting Visual Studio [...]": because you may be using IIS Express or ASP.NET Dev Server whose are closed when you close the IDE, so locks on files are released since the process holding the locks is no longer running.
And about "why is the file still locked?[...]" it could be because the file stream isn't closed because sometimes the thread may not end successfully and the locks aren't released.
As other answer said, check how using block may avoid that IDisposable objects wouldn't be disposed:
// FileShare.ReadWrite will allow other processes
// to read and write the target file even if other processes
// are working with the same file
using var mailinglist_FileStream = new FileStream(#"\foobarFile.txt", FileMode.Open, FileShare.ReadWrite);
using var mailinglist_Reader = new PeekingStreamReader(mailinglist_FileStream);
// Do your stuff. Using blocks will call Dispose() for
// you even if something goes wrong, as it's equal to a try/finally!
I am only reading this File. can i do something similiar to
adLockOptimistic, so that multiple processes can access the File?
Yes, take a look at File.Open method and FileShare enumeration:
File.Open: http://msdn.microsoft.com/en-us/library/y973b725.aspx
FileShare enum: http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx
Learn to use using:
using (FileStream fileStream = File.Open(#"C:\somefile", FileMode.Open, FileAccess.Read))
{
...
}
The using construct ensures that the file will be closed when you leave the block even if an exception is thrown.
Your problem might not be here, but somewhere else in your code. You'll have to go through all your code and look for places where you have opened files but not put it inside a using statement.
An old question but unfortunately the given answers can be not applicable to the question.
The problem specifically in Windows lies in two aspects of Windows behavior:
a) when the handle to the file, opened for writing, is closed, the Microsoft Antimalware Service opens the file to check the newly written data for malware;
b) the OS itself keeps the file opened for some time after all handles to it are closed. This time can be from seconds to many minutes depending on the nature of the file and other factors.
We saw this problem many times in our products and had to provide special support for this case - our kernel-mode attempts to close the file as soon as the last handle to it is closed.
Try using using blocks, it may not fix your lock problem, but it is better form for disposable objects.
using (FileStream mailinglist_FileStream = new FileStream(#"\foobarFile.txt", FileMode.Open))
{
using (PeekingStreamReader mailinglist_Reader = new PeekingStreamReader(mailinglist_FileStream))
{
...
}
}
Also, try closing mailinglist_Reader before mailinglist_FileStream.

FileStream not closing file

I have the following code:
using (MemoryStream str = new MemoryStream())
{
Program.api.GetDocument(result, str);
using (FileStream fileStream = File.Create(filePath))
{
str.WriteTo(fileStream);
}
}
Whenever a file is written, it is always locked afterwards - attempting to delete it or modify it causes Windows to tell me the file is in use, even after closing my application. Am I missing something?
Your problem is most likely caused by Windows Search Indexing which is a part of Windows Search. If you attempt to access the file immediately (or very shortly) after modifying it, you may run into the sort of issues you are seeing. The best way around this is to add retry logic to the file operation you are performing, which waits some small period of times and re-attempts the file op.
If you would like to confirm that the problem is cause by Windows File Search Indexing, you can disable it for the file type and/or location where you are writing your file to see if that makes the problem go away.

Why is File.Create needed to be closed?

The following throws an exception "The process cannot access the file 'D:\MyDir\First.txt' because it is being used by another process."
static void Main(string[] args)
{
Directory.CreateDirectory(#"D:\MyDir");
File.Create(#"D:\MyDir\First.txt");
File.WriteAllText(#"D:\MyDir\First.txt", "StackOverflow.com");
}
However following works:
using (File.Create(#"D:\MyDir\First.txt"))
{
}
or
File.Create(#"D:\MyDir\First.txt").Close();
Why? What in File.Create needs to be closed?
File.Create is doing more than you think here. It's not just creating the file, it's also returning an active stream to the file. However, you're not doing anything with that stream. The using block in your latter example closes that stream by disposing it.
Note also that this is a significant clue about the return value:
File.Create(#"D:\MyDir\First.txt").Close();
(It actually wasn't intuitive to me when I first read your question, but looking back at it this line of code actually says it all.)
Your next step, calling File.WriteAllText also does more than you think. According to the documentation, it:
Creates a new file, writes the specified string to the file, and then closes the file.
So it would seem that your File.Create call isn't really needed here anyway.
Because it opens a file stream, which is a class managing some operating system low-level resources and those must be released in order to let other operations in other threads, and even in other applications, access to the file.
You don't actually need to call File.Create() to then be able to call File.WriteAllText().
File.WriteAllText() will create a new file and write to it then close the file all in one handy method.
If the file already exists it'll be overwritten.
The MSDN docs for File.Create() explain this:
The FileStream object created by this
method has a default FileShare value
of None; no other process or code can
access the created file until the
original file handle is closed.
Basically until the file create is closed the file cannot be access by another process (in this case your attempt to write to it).
File.Create(string) returns a FileStream object that holds the file open. Even though you are not keeping a reference to FileStream object in a variable, it still exists. The object is eligable for garbage collection, and when that happens the file will be closed, but there is no predicting when the garbage collection will take place.

.NET: IOException for permissions when creating new file?

I am trying to create a new file and write XML to it:
FileStream output = File.Create(Path.Combine(PATH_TO_DATA_DIR, fileName));
The argument evaluates to:
C:\path\to\Data\test.xml
The exception is:
The process cannot access the file 'C:\path\to\Data\test.xml' because it is being used by another process.
What am I doing wrong here?
UPDATE: This code throws the same exception:
StreamWriter writer = new StreamWriter(Path.Combine(PATH_TO_DATA_DIR, fileName));
UPDATE 2: The file I am trying to create does not exist in the file system. So how can be it in use?
UPDATE 3: Changed to a new file name, and now it works. I'm not sure why. Perhaps I unknowing created it in the first call, and it failed on subsequent calls?
The message means that another process is using that file. If you have it open it could be using it, or when it was originally created if the stream was not closed properly that could do it also.
First check to make sure you do not have it open. I would try to change the fileName and see if you get the same error. If you do get the same error than some place in your code it is not closing a stream that when it is done with the file.
Your program keeps a handle on your file after it's being created to return to your FileStream object. Because you don't specify the access to it, perhaps it won't let you get a grab on it. Perhaps should you consider closing it, and then reopen it in a proper manner by specifying how you want it open (ReadOnly, ReadWrite, WriteOnly) ?
Not trying to sound insulting, but does the folder exist? Does the file already exist but is hidden by the system? And does the user account that is running the program have write permissions to the folder? Have you tried creating a file using a different method (like with File.WriteAllText(<path>, "Testing") just to see if it's your particular call to File.Create?

Proper methods to have multiple processes reading the same file?

I have many processes reading a file stored on a network share. Originally I was only able to have one process read the file, all the others would throw exceptions. I implemented the following code to deal with that:
using (StreamReader fileStreamReader = new StreamReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
content = fileStreamReader.ReadToEnd();
}
This let multiple processes read the same file, however it still seems to have issues, because sometimes multiple processes still can't access the file. Yet I can go back later when the file isn't in use and open it just fine. Right now I have some retry behavior with random delays implemented that so far, seem to help. It seems a little quirky to me to do it this way, so what would be a better method?
This is the weird part, the exception I'm getting is not from file IO at all, it's from a library called CommStudio. In short, I dump the file to a string, i modify it slightly, dump it into a memory stream, and ship it off over ymodem on rs232. The exception is telling me the remote system has canceled. The device getting the data reports that there was a transmission error, which usually means that an incomplete/empty file was received.
Normally I would blame the library on this, but it works flawlessly at desk-testing and when there is only one process accessing the file. The only thing that really seems to be consistent is that it is likely to fail when multiple processes are accessing a file.
had a similar problem but not allot of time to find an ideal solution. I created a webservice and stuck the file local to the webservice app.. then created a simple one liner GET API which was called over the office intranet.. thus ensureing only the calling application edited the log file.. messy but functional.
I have had a similar problem in the past. Try changing how you access the file to something like this.
//Use FileInfo to get around OS locking of the file
FileInfo fileInfo = new FileInfo(path);
//I actually wanted unblocked read write access so change your access and share appropriately
using (FileStream fs = fileInfo.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
{
//I'm using CopyTo but use whatever method matches your need
fileInfo.CopyTo(Path.Combine(destination, fileName), false);
}

Categories

Resources