Check if file is in use [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.
Hi guys I need some help. I'm trying to open a textfile on a servern from multiple clients at the same time so I'm not locking the file when reading from it. Like this:
new StreamReader(File.Open(logFilePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
Now I'm trying to check if this file is used by any of the clients (because I want to write something new to it), but since I'm not locking it when reading from it I don't know how to do this. I can't try to open and catch an exception because it will open.

Do you can try this?
Or watch this question already asked here ->Is there a way to check if a file is in use?
protected virtual bool IsFileLocked(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();
}
//file is not locked
return false;
}

I can't try to open and catch an exception because it will open
Why ? It's a valuable option to work in that way.
By the way you can also create a some empty predefined file, say "access.lock", and others, in order to understand if the actual file is locked check on lock file presence:
if(File.Exist("access.lock"))
//locked
else
//write something

Related

IOException unhandled - "Cannot access file because it is being used by another process" [duplicate]

This question already has answers here:
File being used by another process after using File.Create()
(11 answers)
Closed 8 years ago.
I am getting this error every time I try to read a file after it is being created. To follow the process:
The file is created using
File.Create(filename);
I then attempt to read that file, using:
StreamReader rdr = new StreamReader(filename); //error catches here
I get the error:
The process cannot access the file '(filename)' because it is being used by another process.
Is this occurring because I haven't closed the file after creating it? How do I do that? Does File.Close(fileName); work?
File.create probably returns filestream. Use
file.create().close();
Yes, you have to close the file first.
From the MSDN article:
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.
So you have to assign the return of File.Create, which is a FileStream, then close the handle to said stream in order to access the file.
yeah,it's because you have opened the file,if open again,it will throw the exception.You should use it like this:
using (FileStream fs = File.Create(path))
{
}
using (StreamReader sr = new StreamReader(path))
{
}

How to save excel file without GUI notifications?

I have an app that is running on a server and that has to write some stuff to excel files. When I want to save and close files I'm getting trouble when the files are open by other machines and users. Excel opens dialogs to ask for filenames but it is running on a server there is no user to close the dialogs. So when the file is open and cannot be written to it should be skipped with no GUI asking for filenames.
Workbook book = excel.Workbooks.Open(filename);
Worksheet sheet = (Worksheet) book.Worksheets.get_Item(1);
// write stuff in cells
book.SaveAs(filename);
book.Close(false);
How can I make excel to try to save the file and then close is no matter what ?
(In my app there is no lost data, it can be written to the excel files later anyways)
file exists → overwrite
file open → don't save, just close
Looks like this answers the question, check if the file is in use before you choose to save or skip.
Is there a way to check if a file is in use?
protected virtual bool IsFileLocked(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();
}
//file is not locked
return false;
}
To check if a file exists you can use
if (File.Exists(filename)){
// if the file exists
book.Save();
}
else{
//if the file doesnt exist
book.SaveAs(filename);
}
All problems might be solved if I set the share options for the one file that I must update. So that multiple users can update the file simultaneously: Menu → Extra → ...
This doesn't solve the problem to 100% but better than nothing:
private static void saveAndClose(Workbook book, string filename)
{
try
{
File.Delete(filename);
}
catch { }
if (!File.Exists(filename))
book.SaveAs(filename);
book.Close(false);
}

c# check if file is open

I need to verify if specific file is open to prevent the copy of that file.
I try lot of examples but any doesn't work! I try, for example, this:
protected virtual bool IsFileLocked(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();
}
//file is not locked
return false;
}
I need orientation... where am I fail? suggestions?
If you want to know whether your application already had the file open, you should just save the FileStream in a field, and reset the field to null when you close the stream. Then you can simply test and get the FileStream of the file.
If you want to know whether another application already has the file open, then there is not much you can do. You'll might get an exception when you try to open the file. But even if you knew, then you wouldn't be able to prevent the copy of that file, because you don't have a reference to the file or its FileStream in your application.
You can suffer from a thread race condition on this which there are documented examples of this being used as a security vulnerability. If you check that the file is available, but then try and use it you could throw at that point, which a malicious user could use to force and exploit in your code.
Your best bet is a try catch / finally which tries to get the file handle.
try
{
using (Stream stream = new FileStream("MyFilename.txt", FileMode.Open))
{
// File/Stream manipulating code here
}
} catch {
//check here why it failed and ask user to retry if the file is in use.
}
or
see this another options
https://stackoverflow.com/a/11060322/2218635

File.Open doesn't throw IOException when File.Move does

I face weird problem with IOException on different servers. Here is my story:
I have win server (C#) that monitors folder for file changes. Also, a FTP server (WinSSHD) is pointed on same folder. When someone uploads a file WinService checks is write complete or not. If file is uploaded WinService renames it via File.Move method.
Is write complete check is made by File.Open method. Like this:
public static bool IsWriteComplete(string filePath)
{
bool isWriteComplete;
FileStream stream = null;
try
{
stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
isWriteComplete = true;
}
catch (IOException)
{
isWriteComplete = false;
}
catch (Exception ex)
{
isWriteComplete = false;
}
finally
{
if (stream != null) { stream.Close(); }
}
return isWriteComplete;
}
For some reason on one server it works perfectly (Win2003SP2) and on another one (Win2003SP1) is not working at all. The IsWriteComplete method says True, WinServer tries to move file and dies by IOException later. I haven't found any references regarding such issue.
To fix the issue I replaced File.Open by File.Move.
Before:
stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
After:
File.Move(filePath, filePath);
And now it works on second server (Win2003SP1) and doesn't work on first one (Win2003SP2).
Does anybody know why it works as such?
When you use File.Open you have a "race condition", even if you use FileShare.None - after you close the file, another thread/process can sneak in and lock the file (open it) before you call File.Move. This other process might not be the FTP server, but could be something you are not even aware of, such as a virus checker. Thus you should use File.Move instead of File.Open, and catch the IOException if the File.Move fails, and then retry, until it succeeds.
When you use FileShare.ReadWrite|FileShare.Delete, you allow other processes to read, write or delete the file while you're opening it. On the other side, you can open the file while others also access it. So, try FileShare.None to open the file exclusively, which should fail as long as the file is in use by the FTP server.
Also, you should use FileAccess.ReadWrite to make sure that you have full access to the file. You do not know how the FTP server locks the file, maybe it allows other processes to open the file in read-mode and declines write mode while the upload is still in process. So, FileAccess.ReadWrite is better.
MSDN reference: http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx and http://msdn.microsoft.com/en-us/library/system.io.fileaccess.aspx
About your code:
catch (IOException)
{
isWriteComplete = false;
}
catch (Exception ex)
{
isWriteComplete = false;
}
The catch block for IOException is not neccessary if you also catch Exception...
Alternatively, you can check in other way then open method.
FileInfo fileInfo = new FileInfo(filePath);
bool isNormal = ((fileInfo.Attributes & FileAttributes.Normal) == FileAttributes.Normal);
//or
bool isReadOnly = ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly);
You can find the method in either way in order to understand whether file is available or not. And you can continue based upon the status.
Please let me know if you are looking for some other things.
Found the root cause of the behavior.
There was different FTP service installed: Techia. For some reason Tectia doesn't set write lock on uploading files. That's why File.Open(filePath, FileAccess.Write) doesn't throw IOException.

Writing to file best practises (locked files/overwriting)

If I am working with files in C#, what is the best way to check if a file is locked in C#?
If I use File.OpenWrite(), which returns a FileStream, and this returns CanWrite = false, is this a way of checking so?
Also, what is it wise to write to just one location in my code? So I specify a path to write to like "TestExample.txt", but then if I run my code, successfully write to the file, run again, the same data will be in there. Is it possible to overwrite the data already in a file altogether? Or do I need to manually delete (I know this sounds naive).
Thanks
File.OpenWrite will throw an IOException if the file is locked, so calling that method and then checking the CanWrite property would not be a good approach. You will need a try-catch handling the IOException.
If you want to replace the contents of your file, you can simply delete it before writing to it (if it exists):
try
{
if (File.Exists(fileName))
{
File.Delete(fileName);
}
using (FileStream stream = File.OpenWrite(fileName))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write("your content");
}
}
catch (IOException)
{
// the file is locked
}

Categories

Resources