Check if a file is open [duplicate] - c#

This question already has answers here:
Is there a way to check if a file is in use?
(20 answers)
Closed 6 years ago.
Is there a way to find if a file is already open or not?

protected virtual bool IsFileinUse(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
return false;
}

As #pranay rana, but we need to make sure we close our file handle:
public bool IsFileInUse(string path)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentException("'path' cannot be null or empty.", "path");
try {
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { }
} catch (IOException) {
return true;
}
return false;
}

If you mean that you want to check if a file is open before you try to open it, then no. (At least not without going low level and examine every file handle that is open in the system.)
Besides, the information would be old when you get it. Even if the test would return that the file is not open, it could have been opened before you have a chance to use the return value.
So, the proper way to handle the situation is to try to open the file, and handle any error than may occur.

Agreed. I would create a designated class which wraps the open file logic or at least the test (IsFileAvailable). This will allow you to place the exception management with a class specifically responsible and make it reusable. You may even apply further logic, such as testing the file size to see if the file is being written to etc, to give a more detailed response. It will also make your consuming code much cleaner.

Related

Having some trouble to delete a file using FileStreams in C#

I'm writing a program that uses text files in C#.
I use a parser class as an interface between the file structure and the program.
This class contains a StreamReader, a StreamWriter and a FileStream. I use the FileStream as a common stream for the reader and the writer, else these two will conflict when both of them have the file open.
The parser class has a class variable called m_path, this is the path to the file. I've checked it extensively, and the path is correct. OpenStreams() and and ResetStreams() work perfectly, however after calling CloseStreams() in the delete() function, the program goes to the catch clause, so File.Delete(m_path) won't get executed. In other situations the CloseStreams() function works perfectly. It goes wrong when I'm trying to close the StreamReader (m_writer), but it does give an exception (File is Already Closed).
/**
* Function to close the streams.
*/
private void closeStreams() {
if (m_streamOpen) {
m_fs.Close();
m_reader.Close();
m_writer.Close(); // Goes wrong
m_streamOpen = false;
}
}
/**
* Deletes the file.
*/
public int delete() {
try {
closeStreams(); // Catch after this
File.Delete(m_path);
return 0;
}
catch { return -1; }
}
I call the function like this:
parser.delete();
Could anybody give me some tips?
Your File.Delete(m_path); will never be called, because you get an exception here:
private void closeStreams() {
if (m_streamOpen) {
m_fs.Close();
m_reader.Close();
m_writer.Close(); // throws an exception here
m_streamOpen = false;
}
}
The exception is "Cannot access a closed file"
The cause is explained in the documentation of Close() in StreamReader:
Closes the System.IO.StreamReader object and the underlying stream, and releases any system resources associated with the reader.
There are also some articles about this behaviour:
Does disposing streamreader close the stream?
Is there any way to close a StreamWriter without closing its BaseStream?
Can you keep a StreamReader from disposing the underlying stream?
Avoiding dispose of underlying stream
You should consider re-writing your code and use using() statements.
However, I experimented a bit with your code, and it worked with calling Close() in other order:
m_writer.Close();
m_reader.Close();
m_fs.Close();
However, I assume that this works only by coincidence (I used .NET 4.0 and probably this will not work in another .NET version). I would strongly advice to not do it in this way.
I tested this:
using (FileStream fs = new FileStream(m_path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
using (StreamReader reader = new StreamReader(fs))
using (StreamWriter writer = new StreamWriter(fs))
{
// so some work here
}
File.Delete(m_path);
But, I know that this may not be for you, since you may want the read and write streams available as fields in your class.
At least, you have some samples to start with ...
File.Delete should work, either you didn't call your delete method, or m_path is an invalid path

File in use error when deleting a folder

I am trying to delete a folder but am getting the following error message:
The process cannot access the file .it is being used by another process.
string target_dir="D:\\projectpath\\page";
if (Directory.Exists(target_dir))
Directory.Delete(target_dir, false);
How can I resolve this error?
It looks like the file is locked by some other process. This could happen if when reading/writing to it you forgot to dispose the stream reader/writer and you leaked the unmanaged handler to the file.
For example if you used the following code to read from the file:
StreamReader reader = new StreamReader(fileName);
string contents = reader.ReadToEnd();
and you never release the reader, the file will be locked. The proper way is to wrap IDisposable resources such as Streams and StreamReaders in using statements:
using (StreamReader reader = new StreamReader(fileName))
{
string contents = reader.ReadToEnd();
}
If on the other hand the file is locked by some other external process to your application then there's very little you could do about it, other than killing this process.
I think on the surface, your problem should be apparent: the file is in use by something else, so you can't delete the directory it resides in. If there was a way to "force delete" the file, it could cause other programs to crash. I'd recommend catching the error and either logging it or displaying it to the user, so they can decide if they really want to delete the in-use file.
If you MUST delete the file, you could take a look at:
Using C#, how does one figure out what process locked a file?
And once you know what the process is, you can then kill it, which should free up the file. Again, this isn't a good practice and should only be used in exceptional circumstances.
To delete the diectory you must have the correct Permissions.
var target_dir = "D:\\projectpath\page";
var isWriteAccess = false;
try
{
var collection = Directory.GetAccessControl(target_dir)
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
if (collection.Cast<FileSystemAccessRule>().Any(rule => rule.AccessControlType == AccessControlType.Allow))
{
isWriteAccess = true;
}
}
catch (UnauthorizedAccessException ex)
{
isWriteAccess = false;
}
catch (Exception ex)
{
isWriteAccess = false;
}
if (!isWriteAccess)
{
MessageBox.Show("no access to directory.");
// Handle here close and kill the blocking process
}
else
{
Directory.Delete(target_dir, false);
}
}

Is it possible to tell if user opened or downloaded a file?

I have a controller returning
return base.File(filepath, "application/pdf", "filename");
This creates a dialog for open/save. Is it possible to detect whether the user chooses save or open?
Alternatively, if I return this:
return base.File(filepath, "filename");
It forces the user to download from a left-click. If they right-click->Save File As, then they have the option to save. Is it possible to detect the difference between open and save here?
No. Server does not receive any information from the client after request to get the file. You can confirm it with a HTTP watch utility like Fiddler.
You can try this method. This will tell you whether your file is in open state by another process or not
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
// file is used by another process
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}

is file creation atomic in windows xp?

HI,
I would like to use the file system as a lock between two processes, on windows xp.
i.e. given a file name "file_lock", a process acquires the lock by trying to create
the file "file_lock" if it doesn't already exist. If already exists, fails to get the lock.
i.e.
FileStream fs=new FileStream("c:\\file_lock, FileMode.CreateNew);
Will this work? Is file creation if file doesn't already exist atomic?
Thanks!
Yes it will work. But not as well as a Mutex for many reasons including:
What if the user doesn't have access to create that file?
When your app crashes, the system cleans up Mutex locks. It won't delete your file for you.
Why introduce the overhead and risk of disk IO unnecessarily? (and I'm not sure if this is possible, but while the file is open, a user can rename or move it, right?)
It's more code.
As the question has been tagged as C#, this answer no longer applies, but I would like to leave it in case it would be helpful for others in the future.
If you're using Java, you could use java.nio.channels.FileLock.
To use it, do something like this:
import java.io.RandomAccessFile;
import java.nio.FileLock;
...
RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileLock lock = raf.getChannel().tryLock(0L, Long.MAX_VALUE, false);
if (lock != null && lock.isValid()) {
// You've acquired the lock!
else {
// You did not acquire the lock
raf.close();
}
Note: This protects against access from other processes, but not other threads. You'll need to use your own internal synchronization for that (locking on raf would probably work).
If you want to use the file as a sync lock i suggest you the next procedure.
Check for the file lock/exists
If file is locked the other process is working
If file doesn't exists or have no lock you can adquire it
Open the file adquiring the lock
This code can help you checking for the lock.
public static bool isFileLocked(string filename)
{
if (!File.Exists(filename)) throw new FileNotFoundException("File not found!", filename);
FileStream fs = null;
try
{
fs = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
return false;
}
catch (IOException)
{
return true;
}
catch (Exception)
{
throw;
}
finally
{
if (fs != null)
{
fs.Close();
fs = null;
}
}
}
HTH!

FileSystemWatcher - how to determine when file is closed?

I'm downloading a file from a server and opening it using Process.Start() and attaching a file watcher to the file to catch any changes and re-upload them to the server.
Is there anyway to determine when the file has closed using the FileWatcher or any other method? The problem being I can't decide how to stop watching the file and I don't want it watched indefinitely?
Any ideas?
Thanks in advance
Jon
What I did was put a 5 minute loop and just watch for the file to be available. That way I could give it time to free up, but yet still had a definitive time. If it hasn't cleared by 5 minutes in my system something is definetely wrong. You should set your time limit to your circumstances. I got this idea from somewhere, no idea where anymore.
DateTime EndTime = System.DateTime.Now.AddMinutes((double)timeOut);
while (System.DateTime.Now <= EndTime)
{
try
{
using (Stream stream = System.IO.File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
if (stream != null)
{
break;
}
}
}
catch (FileNotFoundException)
{
//
}
catch (IOException)
{
//
}
catch (UnauthorizedAccessException)
{
//
}
System.Threading.Thread.Sleep(sleepTime);
}

Categories