Issue with check if Excel file is already open - c#

I'm using the below method to check if a file is already in use... seems to work just fine but my problem is that if I have excel open, sometimes the filestream actually opens and leaves open the excel file that its currently checking.
Anyone know why the file is actually opening and not closing when it leaves the using statement?
EDIT: More to the above, it opens the excel file and then it display a message box telling me that the file is available to Read/Write
I put the below in the comments but I think it pertains to my usage of the IsFileLocked code and may actually be the real cause??
I'm using the IsFileLocked code along with a filewatcher. When the filewatcher goes off I check if the excel file is still in use and if its not in use then I query data back from that excel file.
Process.. 1.) Excel file has changed or is being changed by another user 2.) make sure its still not in use with the IsFileLocked method 3.) if file is no longer in use then query data back from the excel file but sometimes the excel file actually opens on the user's computer who is watching excel files for changes.. if this makes sense
protected virtual bool IsFileLocked(string path)
{
try
{
using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, 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
{
}
//file is not locked
return false;
}

Related

copy the data from xml file and paste in same file and overwrite using FIle.Copy()

I am trying to copy data of one file and pasting it into the same file which means overwriting it. I learn that overwrite the file data using file.copy() cannot be possible. but from the one of the post says that if I use File.Copy(Source file, destination file, true) than overwrite is possible. I tried to use but it didn't work. if anyone have solution for that than it will be big help.
public void EditRole(string oldRole, string newRole)
{
if (File.Exists(roleXMLLoc))
{
XDocument doc = XDocument.Load(roleXMLLoc);
var edit = doc.Element("Roles").Elements("Role").Where(x => x.Value == oldRole).SingleOrDefault();
edit.Value = newRole;
doc.Save(roleXMLLoc);
if (File.Exists(userPermissionLoc))
{
File.Copy(userPermissionLoc, userPermissionLoc, true); SaveData();
}
}
}
To read or write files you should open a Stream (https://learn.microsoft.com/en-us/dotnet/standard/io/). If you need to read and write in the same time, then you should use 2 separate streams for reading and writing into 2 separate files. Operating system will protect file from being opened by 2nd stream, otherwise you would fall into problems of concurrency: you read the inactual data that is already being changed by writing stream.
The logic can be:
Read file and close Reading stream. Then open file for writing and do what you need.
OR
Open Reading stream for fileToRead.xml and open Writing stream for temporary fileToWrite.xml. After you done, you can close both streams, remove the source file and rename the new file.

test if file is complete and not locked by other process/(external) program/thread/

the situation: Files are being dumped in a folder. This folder is being constantly monitored with own logic. When files are in the folder they are being processed automatically. We only want to process files that are fully copied into the directory.
In case we copy a large file e.g. 100MB to a folder, we don't want to process that file until it is fully copied ('complete').
Currently we test this with this code:
FileStream fs = null;
try {
fs = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
// file is 'complete'
} catch (System.Security.SecurityException) {
// file is locked, don't do stuff (maybe Windows Explorer is still copying).
}
catch {}
finally {
fs?.Close();
}
As I think the SO User Hans Passant once said, the only way to test this is to try opening this file.
This code works but is 'old'.
Are there more efficient methods/techniques to implement and test this? (as performance is critical, the faster, the better).

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

Deleting a temp file that is open c#

i have written some pdf files to a temp directory and these get displayed as a thumbnail that the user can view. when i close my form i clean up all of the files in the temp directory.
If however the user has one of the thumbnails open and then closes my application - it deletes the files and then throws an exception because the pdf is open in another process and cant be cleaned up.
I guess this is a shocking programming decision by me, but i am still a novice! How should i account for this in my code?
Thanks
You can detect if the file is in use by using code similar to below, then use that to warn the user that a file can't be deleted.
Unfortunately you can't delete a file that is in use.
public static bool IsFileInUse(string pathToFile)
{
if (!System.IO.File.Exists(pathToFile))
{
// File doesn't exist, so we know it's not in use.
return false;
}
bool inUse = false;
System.IO.FileStream fs;
try
{
fs = System.IO.File.Open(pathToFile, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Read, System.IO.FileShare.None);
fs.Close();
}
catch (System.IO.IOException ex)
{
string exMess = ex.Message;
inUse = true;
}
return inUse;
}
You should catch that exception (in catch block you can inform user to close that file or it will not be deleted), and if the temp directory is yours you can try to delete it when application starts (or when it ends again), if its windows temp directory, then it does not matter that much
Tools like File Unlocker can release a file. However I think this could make programs depending on the file crash...
Maybe you can look up how they unlock files or manage to execute the unlocker via Process.Start to unlock your file and delete it.
However if it's you blocking the file you should try and fix this in your programm. Maybe you should dispose all loaded files (filestreams etc) before trying to clean it up.

Categories

Resources