Read-only file in use right after read-only set to false - c#

I'm trying to use the following code to delete a read-only file.
var fileInfo = new FileInfo(saveLocation);
fileInfo.IsReadOnly = false;
fileInfo.Delete();
When it gets to the third line, the following exception is thrown
Message: The process cannot access the file '\\filepath\filename.pdf' because it is being used by another process.
Note: \\filepath\filename.pdf is not the actual file path, I'm just using it to replace a longer path
I've checked the file, and before the code runs, it is set to read-only, and after the code runs, it is not anymore.
Am I incorrect in thinking that when a file is opened as read-only it is not considered to by in use? I'm pretty sure that is true for Microsoft office files suck as .xlsx files, but maybe not for PDFs?
Ultimately, my goal is to be able to push an updated version of this file to a shared location even if some user has the file open on their machine, which is why I initially set it to be read-only.

Message: The process cannot access the file '\filepath\filename.pdf' because it is being used by another process.
This is not the same as the file being read-only.
You can find out in code which process is locking the file
https://stackoverflow.com/a/20623311/141172
You can also find out from the command line
UPDATE
Based on your comments, it seems like you may want an exclusive lock on the file for the duration that you are processing it
open file in exclusive mode in C#
Command-line tool for finding out who is locking a file

Related

c# FileSystemWatcher fires on multiple clients

I'm using a FileSystemWatcher to watch a directory. I created a _Created() event handler to fire when a file is moved to this folder. My problem is the following:
The files in this directory get created when the user hits a "real life button" (a button in our stock, not in the application). The FileSystemWatcher take this file, do some stuff in the system and then delete it. That wouldn't be a problem when the application runs only once. But it is used by 6 clients. So every application on every client is trying to delete it. If one client is too slow, it will throw an exception because the file is already deleted.
What I'm asking for is: Is there a way to avoid this?
I tried using loops and check if the file still exists, but without any success.
while (File.Exists(file))
{
File.Delete(file);
Thread.Sleep(100);
}
Can someone give me a hint how it could probably work?
Design
If you want a file to be processed by a single instance only (for example, the first instance that reacts gets the job), then you should implement a locking mechanism. Only the instance that is able to obtain a lock on the file is allowed to process and remove it, all other instances should skip the file.
If you're fine with all instances processing the file, and only care that at least one of them succeeds, then you need to figure out which exceptions indicate a genuine failure and which ones indicate a failure caused by the actions of another instance.
Locking
To 'lock' a file, you can open it with share-mode FileShare.None. This prevents other processes from opening it until you close the file. However, you'll then need to close the file before you can delete it, which leaves a small gap during which another instance could open the file.
A better solution is to create a separate lock file for that purpose. Create it with file-mode FileMode.Create and share-mode FileShare.None and keep it open until the whole process is finished, including the removal of the processed file. Then the lock file can be closed and optionally removed.
Exception
As for the UnauthorizedAccessException you got, according to the documentation, that means one of 4 things:
You don't have the required permission
The file is an executable file that is in use
The path is a directory
The file is read-only
1 and 4 seem most likely in this case (if the file was open in another process you'd get an IOException).
If you want to synchronize access between multiple clients on the same computer you should use a Named Mutex.

Difference between File.Copy and File.Move

Nowadays I am dealing with a small application which updates the mssql's compact database files on an iss server.
I've preferred to use SSIS to organize the flow. For couple of days it worked well, but then started to give errors.
In SSIS I've used the "File System Task"s "Move File" operation to move generated files from a folder to iss server's shared folder. If it fails, in case of a locked file, it tries it later. But I've seen that sometimes the files in the destination folder started to disappear.
Then I've decided to write custom code. I've removed the "File System Task" and put a "Script Task" instead of it. And write a couple of lines in it.
string destinationFile, sourceFile;
destinationFile = Path.Combine(Dts.Variables["FileRemoteCopyLocation"].Value.ToString(), Dts.Variables["CreatedFileName"].Value.ToString());
sourceFile = Path.Combine(Dts.Variables["OrginalFilePath"].Value.ToString(), Dts.Variables["CreatedFileName"].Value.ToString());
bool written = false;
try
{
File.Copy(sourceFile, destinationFile, true);
File.Delete(sourceFile);
written = true;
}
catch(IOException) {
//log it
}
if (written)
Dts.TaskResult = (int)ScriptResults.Success;
else
Dts.TaskResult = (int)ScriptResults.Failure;
It worked well. But I tried it by locking the destination file. I've connected the destination file in Sql Server Management Studio (it is an sdf file). And surprizingly it works too.
And I've tried it from operating system, by copying the source file and pasting it to the destination. Windows 7 asks me if I want to overwrite it and I say yes and it overwrote the file (copy and replace) I use with another process, no warning no error.
But if try to rename or delete it does not let me to do that. Or if I try to cut and paste it (Move and Replace) it says "you need permission to do this action".
As I understood, "Copy, delete" and "Move" are totally different things. And I still can not understand how can I overwrite a locked file.
Any ideas?
File.Move method can be used to move the file from one path to another. This method works across disk volumes, and it does not throw an exception if the source and destination are the same.
You cannot use the Move method to overwrite an existing file. If you attempt to replace a file by moving a file of the same name into that directory, you get an IOException. To overcome this you can use the combination of Copy and Delete methods
Answer orignal from : Difference between in doing file copy/delete and Move
Although the subject is not new, I would like to share my experience. I had to change the pdf file names in my digital library. When I copied about 10,000 legal articles to another folder by changing their names using the File.Copy() method, half of it took about 15 minutes, and I stopped the process because of it takes so long. Then when I tried the same thing with the File.Move() method, the result was incredible for me: It took less than 1 minute to move the whole thing. Of course, I don't need to say that all these are directly related to the system features.

How can I delete a file that is in use by another process?

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.

file/folder is already in use, renaming,deletion problem ? c# iis

I am trying to renme a file/folder, when i try to rename a file, i got an error, file is already in use, it is just my guess that it is caused by w3wp.exe iis process? some time its says, access to the path is denied, although the file does exist, and there are no special permission, i have all the permission to copy/delete/move and everything for the file/folder.
How to fix this problem.
the folder contains jpeg files.
this happen: when i copy a file then try to rename it.
this happen: when i rename a file then try to delete it.
what i mean to say is that it happen when i already use a file operation then for second time it gives me this error :(
this is the error:
The process cannot access the file 'C:\images\audio-aif-old.png' because it is being used by another process.
file.move(source,destination);
i am using C#. iis 6, asp.net.
Directly , ans is no. But you can delete old copy and create a new copy. See this. http://www.aspnettutorials.com/tutorials/file/file-renfile-aspnet2-csharp.aspx
Some other program must relinquish the file. If you've written a program that's still running then that must be shut down. If the file is currently open for writing you must also ensure that it's been appropriately closed. Try creating another file and see if you have the same problem with that one.

How to wait for a file to be copied completely?

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.

Categories

Resources