Close file if open through window explorer - c#

In my application, I need to delete files and then remove the directory that contains those files. It works great if none of the files are open.
But if any file is open (i.e. index.txt) , it is successfully deletes from directory and at the time of removing the directory it throws an exception like file is used by other application.
Is there any way to close the open file in C# using p/invoke or anything else?

The only way to delete files currently held open by other applications is to have those applications release the lock on the file (usually by closing the file) or by terminating the application itself.
Obviously, forcing an external application to terminate in order to delete a file that the app is currently holding open can often be a recipe for disaster!

If you have noticed, when you open a MS Office file it creates a "shadow" file nearby - that is something like in RAM stored document. So if you delete the real file the "shadow" file remains in directory. So the RAM uses your directory.
In other words I think it is not possible to do it in C#.

Basically, the only way to break this link and be sure about it is to kill other processes from yours. There are various ways to do this, that have been pointed out, but a better question is whether you should.
I recommend looking into a try-catch pattern and making your application report the error to the user, instead of aggressively trying to delete a document which may be open for a very good reason from the perspective of the user or even the system itself.
Also note that killing outside processes is not a garuanteed solution, as there are multiple cases where the "kill outside process" step could fail (targeted process is run as Administrator and your app isn't, targeted process it set up as a Windows Service and restarts itself before you finish deletion, targeted process is a system-critical process which can't be terminated, ect.)

The below code works great with .doc files.
But doesn't work with .txt file. It doesn't throw any exception for .txt
Still searching for solution that works with .txt files.
I am opening files through Window Explorer, not via any code.
public static void Main()
{
String file;
file = "C:\\Temp\\test.doc";
bool b=IsCloseFile(file);
if (b)
MessageBox.Show("File Open");
}
public static bool IsCloseFile(string file)
{
FileStream stream = null;
try
{
stream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException e)
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
return false;
}
}

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.

Can't delete file (process cannot access the file because it is being used by another process)

I try to delete files from a directory I specify. The first time it works great, but the second time it gives the next exception:
The process cannot access the file 'C:\Users\DAAGEU\AppData\Local\Temp\Manual_Avatar\AdamBody_1K_Pants_Black_Blended.jpg' because it is being used by another process.
foreach (String file in Directory.GetFiles((userDirectory)))
{
try
{
//using (FileStream fs = new FileStream(file, FileMode.OpenOrCreate))
//{
//fs.Unlock(fs.Position, fs.Length);
//fs.Dispose();
//fs.Close();
//}
File.Delete(file);
}
catch (Exception)
{
throw;
}
}
It are only the images that seems to be "locked". I found some stuff on stackoverflow but nothing helped? I use some 3rd party software to generate the image.
Any 1 knows how to fix this or work around it??
ANSWER:
I found the problem. I was using WinForms and in one WinForm I was hosting a WPF control with the image. I found out that I didn't dispose that UC after closing it. So my fault I should have mensioned that also in this question...
Try to delete your file the usual way through windows explorer. If you get that annoying popup there saying Could not delete... It is being used by another person or program you can download Unlocker and have it tell you exactly which process has a lock on it. This little program has been very useful to me throughout the years. It even runs from a memorystick, so installing is an option. Installing it is definitely a plus though since it will automatically pop up with the name of the locking program when you get that popup.

Why can't I create a txt file after having just deleted it?

My program creates a log file when it starts. The user has the option through settings to "clear the log" which calls a method to delete the log file.
//calls for a YesNo prompt to delete log or not
result = objectMessageBox.ReturnDeleteLogPrompt();
if (result == DialogResult.Yes)
{
//throw prompt
if (File.Exists(objectLog.GetLogLocation()) == true)
{
try
{
//delete the log file
File.Delete(objectLog.GetLogLocation());
//throw balloon tip saying log was cleared
ShowBalloonTip("LogCleared");
}
catch (Exception ee)
{
MessageBox.Show("Error thrown deleting log: " + ee);
System.Windows.Forms.Clipboard.SetText(ee.ToString());
}
}
}
Because I have deleted the log file entirely I need to then recreate it. So I call a method that has this:
try
{
//we create a new log file so it seems that the log has just been cleared
objectLog.CreateLog();
}
catch (Exception ee)
{
MessageBox.Show("Error occured while clearing log:\n" + ee);
}
But when it attempts to recreate the log file it throws an error that says:
"System.IO.IOException: The process cannot access the file '~~' because it is being used by another process."
So it seems that during my call to delete the file it keeps accessing it? Do I need to dispose of something when I call the file.delete?
I don't know the details, but there are numerous reasons for why a filename isn't immediately available for recreation after deleting an existing file:
The delete operation is still pending by the operating system
An antivirus program or similar security feature opened up the file in response to it being deleted, for pre-deletion analysis
An antivirus program or similar security feature already had the file open while you were using it, and is still in the progress of responding to your deletion request
Mercurial had this problem on Windows as well. If you executed one command that locked the repository (which was done using temporary files), and then immediately executed another command that either needed to lock, or at least ensure no lock was present, it could fail with the same type of error, the file was in use, even though this was two distinct processes and the first had already exited.
In other words, the timeline was as follows:
hg.exe instance #1 starts up, locks the repository by creating the temp file
hg.exe does what it needs to do
hg.exe deletes the file, then exits
hg.exe instance #2 starts up, attempts to lock the repository, fails because file is in use
Their hack to "fix" this was to simply pick a random filename that wasn't used in the directory, rename the file to that name, and then delete it. This did not solve the problem of the file lingering for a short while, but it did free up the filename and make it available for new files right away.
There already is an accepted answer, but perhaps someone finds this useful (or laugh at it if I missed something obvious again and wasted my time completely)
I had the impression that File.Delete would either delete the file and then return, or otherwise throw an exception - until I read this thread.
The windows API mentions that by calling DeleteFile the file is "marked for deletion on close" since it allows calling delete on an open file. After a file is marked for deletion, an attempt to open it will fail as "Access denied". When the last handle for this file is closed, the file is actually deleted.
If windows actually deletes the file before returning from the last CloseHandle call on the file, in theory this code would guarantee that the file is deleted below the using block:
using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Delete))
{
File.Delete(path);
}
The File.Open would fail if another process currently has the file open.
Note the difference here that File.Delete even succeeds if a file does not exist (unless the directory does not exist).
Instead of deleting and recreating the same file, can you just clear it out?
Something like this should work for you:
FileStream f = File.Open(#[filename], FileMode.Create);
f.Close();
You could use System.IO.FileInfo.Delete to delete the file, and then System.IO.FileInfo.Refresh() before creating the file again. The Refresh should stop the exception from happening on re-creating the file. Or as nycdan says, use the FileMode.Create enum.

Keep multiple copies of file from being opened in WPF app

I have a WPF app, which opens and edits XML files. Currently, the app can be launched multiple times, and several instances can have the same file open. I need to lock the files such that, when one is open, it won't let another instance of the app open the file. I have tried using the FileShare.None attribute when opening the file, as well as FileStream.Lock(), but for some reason, these fail to prevent a separate instance of the app from opening it.
EDIT: Relevant code
try
{
FileStream iStream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
iStream.Lock(0, iStream.Length);
// DO STUFF WITH FILE HERE
}
catch (System.IO.IOException ioException)
{
// Raise exception to higher level, where application will terminate.
throw (ioException);
}
You need to keep file open all the time you are "editing" it from the moment you start editing till closing (assuming you have separate processes for each instance of your app).
Your code looks like you are opening file inside on method and likely close it inside this method either by using "using" as recommended for short file operations or just letting GC to close it. As result you lock file for some time, but release it soon enough for other instances to be able to open it again.
Note that if your application implements some sort of single instance approach this locking may not be enough as all of the open operations will be executed from the same process.

How can I tell when a file has been recently overwritten inside an FTP folder?

I'm writing a Windows Service that needs to take a file from an FTP folder on the local computer and parse the data in that file, and push it to an external source. The file will be uploaded to the FTP folder at some point from some other party, and I can't predict when the file will be uploaded. I need the service to be able to scan the FTP folder and recognize when the file has been recently uploaded to the server, and kick off the parsing process.
I need some know if there's some way in .NET to be able to detect when a file was put into a directory.
There is a similar question in SO about this here, but it wasn't in regards to writing a windows service. Also, the solution seemed to be to monitor the directory itself, but I tested that idea using the DirectoryInfo class and it doesn't work when looking at the LastWriteTime property. The time of the directory doesn't change when I copy and replace a file in the directory.
Note: I can't rely on the create/modify timestamps on the file, being as I don't know how the other party is generating these files.
Use a FileSystemWatcher. That will throw a "Changed" (Or even a "created" I believe) event which you can handle. You'll need to be careful to make sure the file is fully written before you start working with it, but that should get you pointed in the right direction.
EDIT: To Joseph's question about how, here's a static method I keep in my utilities class for just such occasions:
public static bool FileComplete(string filePath)
{
try
{
File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
return true;
}
catch { return false; }
}
Then I just a While(!FileComplete(foo)) {} before my actual file handling.
Take a look at FileSystemWatcher.

Categories

Resources