I have this piece of code, which loads a file into RAM, then loads it as an assembly into an AppDomain (d):
var a = d.Load(File.ReadAllBytes(tmp));
The problem is that when I later try to delete the file located at tmp (right now just using File Explorer), I get an error saying that the file is still open in my program. I even tried using the using keyword with File.Open, and that didn't seem to work either. Can someone please explain why this might be happening, and how to fix it?
ReadAllBytes is supposed to close the file as part of its function. It sounds like something is preventing it from closing, and therefore you cannot delete. Maybe there's an exception happening that needs to be caught.
Here is a similar question with a solution which may be helpful:
Unable to delete some files via System.IO.File in C# console app
Related
I am busy writing an additional module to an existing C# application. In my module I have to generate some data and add it to ZIP archives created by the main program. (Ionic.Zip library is used). In most cases I can successfully update existing archives and store them again. But sometimes (and quite often) this does not work, since, as far as I understand, something in the main program opens a stream to the concerned archive file and fails to close it before I try to access it.
It is absolutely clear that the process that locks the files is the main program itself (tested with a tool based on How do I find out which process is locking a file using .NET?).
I am not aware of any technical possibility to trace down the point in the code where a file is opened without being (somewhere) closed, but it is my hope that such a technique may exist however and that someone could share some information on it.
TIA
When I try to delete a file occurs the following exception:
The process cannot access the file ''
because it is being used by another
process.
My code looks like:
string[] files = Directory.GetFiles(#"C:\SEDocumentConverter\SOURCE");
foreach (string file in files)
{
File.Delete(file);
}
How can I solve this problem?
There is no way to delete a file that's currently being used by another process. You have to close whatever program has that file open first, before you can delete it.
If you don't already know which program that is, you can figure it out using Handle or Process Explorer.
You can P/Invoke the Windows MoveFileEx function, and use the MOVEFILE_DELAY_UNTIL_REBOOT flag, with a NULL destination name. This will delete the file when you reboot.
If the file is being used you're out of luck in trying to delete it. I can't tell you based on your code what process might be using the file(s), but try looking here or here or here, or at any of the other questions that show up as related to this one for guidance regarding this issue, and by all means follow the guidance from #Cody Gray about using Process Explorer.
slightly off topic: But it seems from your code that you are trying to delete all files of your folder.
Well instead of deleting them one by one we have another method Directory.Delete(path, True) which will delete the directory as contained in the string named path. Then you may recreate the directory if you want. But your problem may persist here too.
Another way is to find all open handles to the file and close them forcibly.
Works nice for you, bad for any apps which were using the file.
Could try that in UI with SysInternals ProcessExplorer.
Just rename this file. This will do the thing for whoever tries to write to that location.
Notes:
1) Of course the file is not deleted physically yet. Nice to do the MoveFileEx trick mentioned here around to complete the job.
2) If you want to delete a locked file to write smth new in its place (e.g. during build), just rename the file to a GUID name. If you need the folder to be clean, either use an ignored extension / hidden attribute, or rename the file to a path under %TEMP% (if on the same drive).
3) Not all locked files can be renamed, but it works for me for like 90% practical applications. You can move a file without affecting an open read/write/execute handle, it will continue working with the moved file just good (if moved within the same NTFS volume of course).
4) That's what Windows Installer would basically do before it asks you to please reboot somewhen soon: move the file away from your eyes, schedule to be removed upon reboot. Usually the newly-installed app can be used right away.
Practical Use:
My favorite is with MSBuild. Overriding the <Copy/> task with this stuff makes all the build go linux-way. You don't care if a prev version is still running somewhere, can still build&run. The old app keeps using the old version of the files. The new app loads the newly-written version.
Might be moving to %TEMP% if on the same drive (not my case though). I'd just rename them to an extension which is ignored with the current source control client.
I have a thread which polls a folder for new files. The problem is that it sees a new file and starts working on it even before the file has been completely copied by another process. Because of this the poller gets file used by another process error.
Is there a way to check the file is free to use or get notified? We can certainly use exception handling code, but is there a better way?
Tech: .NET 2.0/C#
Update:
Found out from other answers that if we have access to the app writing the file then better design is to start with some other extension .tmp and then rename it after copying.
The FileStream.Lock could be used if we don't control the source application
We attempt to get a lock on the file before processing it and handle the IOException rather than a generic exception during the attempt to read the file.
See FileStream.Lock on MSDN.
I have written an Add-in for Windows Home Server Console that is supposed to copy and replace some files among other things.
The problem is that one file is already used by HomeServerConsole.exe and therefore I cannot replace it with another. I get "Cannot access file because it's being used by another process".
I'm not sure how to solve this. My first idea was to programmatically close HomeServerConsole.exe and lauch another simple program to do the replacing. How do I do that though?
Another idea was to somehow get HomeServerConsole.exe to unlock the file for me to do my thing and then handing it back to HomeServerConsole. But how?
I've also begun looking at Win32Api to solve the problem but haven't yet found a solution.
How would you go about solving it?
These methods require a reboot:
How to replace in-use files at Windows restart
I am currently doing the following:
I create a file using FileStream braced in the using() tag - Only the file creation takes place within the using statement. The rest of the statements are nearly sequential.
Launch the file I have created using Process.Start()
Read a small bit of meta data from the file using Assembly.ReflectionOnlyLoadFrom()
List the running processes using Process.GetProcessesByName
Kill the Process using Process.Kill
Try to delete the file using File.Delete()
My problem is that my application is locking the file, so when I try to delete it, nothing happens. It throws an exception saying "Access is Denied" if I try to delete, and throws "Another process is using this file" if I try to write to it.
What on earth could be consuming the file from the above (literally all there is)? I have set all references to null, and gone as far as to call the dreaded GC.Collect() and no luck.
When you load assembly it's hosted in the current AppDomain. If you load it using ReflectionOnlyLoad(byte[]) it will load it as shadow and won't lock the file.
var bytes = File.ReadAllBytes(path);
var assembly = Assembly.ReflectionOnlyLoad(bytes);
Currently, the code that blocks the file is Assembly.ReflectionOnlyLoadFrom() and not the writing to the file (assuming the FileStream is disposed before trying to delete). The file will be released only when the AppDomain is unloaded.
Clearly, you are doing something in your code that causes the assembly to be loaded in your own process. Once there, it is stuck and the file is locked until the AppDomain in which it gets loaded gets unloaded. Which is no doubt the primary one, it's stuck until your program terminates.
Pay attention to the Visual Studio Output window, you'll get a debugger notification as soon as it gets loaded. Stepping through your code while watching that window will easily isolate the statement that causes it.
You can do an analysis with the Process Monitor tool. It can capture the call stack of each file access thus should be sufficient to tell you where/when the file is locked.