Cannot write to XML file in another computer from my program - c#

When I write to an XML file, an exception occurs: "Cannot access file because it used by another process". How can I fix that problem?

You can use things like "Process Explorer" (easy to find) on the machine in question to double-check which process is locking a file. If you don't own the competing process, the best you can do is ask the operator to kindly close the file and/or app that is blocking you.
Assuming you do you manage the other process that is locking the file? The most common cause of unexpected locks is files not being closed cleanly. Check that you are religiously closing all file handles after use, ideally using using so that they are closed even in error conditions - for example:
using(Stream dest = File.Create(path)) {
// write to dest
}

Most likely this means another program has this file locked. Try saving in another location and make sure you're properly disposing objects used to write to the file when you're done writing. Also double-check you have proper permissions to write this folder (try creating a basic text file there)
Keep in mind that your program may be running with different permissions than what you are logged in with.

The XML file that you are trying to write to will be currently open by any other process [file opened] and will be in a locked state. You cannot modify a file that has been locked.
Close any file handles that are currently using the resource.

Related

Is it possible to edit a file outside of my running application without closing the attached FileStream first?

I have a Windows Service that's always running as a part of my application. The service uses a TextWriterTraceListener to write to a log file so it's easier for me to debug later if needed.
The TraceListener uses a FileStream object. I thought by using FileShare.ReadWrite in the construction of the FileStream, I would be able to edit this file in Windows Explorer as needed (edit the file and save it/rename the file/move the file), but this does not seem to be the case. The MSDN article on FileShare states: "even if this flag is specified, additional permissions might still be needed to access the file," but is not very clear as to what those permissions might be.
As of now whenever I try to edit that file I keep running into the following error: "The process cannot access the file because it is being used by another process."
Two thoughts:
Regarding FileShare statement that additional permissions might still be needed - that's likely in reference tha while your program says it can handle someone reading or wrting to the file while it has it open, others may still need necessary access permissions (as in ACL) to access files.
The second thought is the reason you're experiencing this is probably because the other program with which you're trying to open the file is trying to open it in exclusive mode (i.e. NOT FileShare.ReadWrite. So that program demands exclusive access and does not receive it because you have it open (even if willing to share).
Test with a program (or write quick one yourself where you know you're setting flag to share) that can open in shared mode to see if it works.
To rename or remove the file, it must be opened with FileShare.Delete. If it is deleted or renamed while you have it open, you may find that subsequent operations on the file will fail with the error "File was removed or deleted".

How to Copy a File that is In Use

I want to provide my users with the ability to post a log file onto my server rather than requiring them to find it and email it to me.
I am using this library http://ftplib.codeplex.com/ to open an ftp session on the server and send the file. There is a bit of renaming involved but that is it.
Unfortunately the log file to be sent is actually open so I got a 'file is being used by another process' exception. This makes sense when I think about it in so far as the log is open while my app is running. I closed it but, of course, uploading is a long process. I put the upload code into a background thread so that the user may continue. However the log cannot be re-opened until the upload is complete. In the meantime there could be some event that should be written to the log.
So I am looking for a way to copy the log and then upload it. What would be the best way to do that? The log is a binary file BTW.
If you don't own the code that has the log file open (ie, it's another app or a closed source dll), you can try doing a File.Copy(<log>, <tempdest>) and send that file, deleting it when you're done. This only sometimes works when you don't have read access to the file.
If you do own the code that is accessing the file in the first place, you want to open it with an explicit ShareMode ie
File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)

Reading a file without preventing other processes from reading it at the same time

I'm making a little app in C#/.NET that watch for the creation of a file and when it is created it gets its content, parse it and write it in another file.
Everything is working fine so far. But the problem is : there's another process that watch for this file as well. My process is only READING the file while the second one reads it and then DELETES it.
My application is making its job but when it reads the file, the other process can't read it and totally crashes (Not made by me and don't have the sources to fix it).
My application is running very fast and other open the files for a very little time to get the content and put it in a variable so it could close the file faster and then parse the content of the file which is in the variable.
I clearly don't know how but I'd like to be able to read the file and let the other read the file at the same time without any hiccups. Is it possible? I still think that there will be a problem about the fact that the file is being deleted after the other app is done parsing it...
Any suggestions or ideas?
Thanks very much!
You can open the file as follows to ensure you don't lock it from other processes:
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// do your stuff
}
But if the other process is trying to open it in exclusive mode, it won't help and it will still crash. There's no way to deal with that other than fixing the code for the other process.
KISS: Can you have the file created in a location which the first program isn't looking at, but your software is - and when you are done processing it you then move it to the current location where the first program is looking?
Otherwise:
You are going to have contention since it's going to be a race to see which process actually "notices" the file first and begins working.
I'm assuming you also don't have any control over the process creating the file?
In that case you might look at PsSuspend or PauseSp - if you can control the other process by suspending it until you are ready for it (done with the file) then that might be viable. Not sure how robust this would be.
There's also still the potential race condition of "noticing" the file and performing an action (whatever it is) - keeping the other process paused perpetually until you want it to run (or killing it and starting it) is the only completely deterministic way to achieve what you want within the constraints.
If you are using an NTFS drive (which is very likely), then you can create a hard-link to the file. Essentially, this duplicates the file without actually creating a duplicate. You can read the file with the hard-link. The other process can delete the file, which will only remove their link to the file. This will leave the file in place for you to read. When your program is done reading the file, it can delete the hard-link, and the file system will see that both links have been deleted, and it will delete the file itself.
This can be done from the command line with
fsutil hardlink create <NewFileName> <ExistingFileName>
Or you can P/Invoke the CreateHardLink function in the Windows API.
Can you create another empty zero bytes file called .reading file which has the same name but extension "reading" to it. Then once first process is done reading the file, rename .reading to .done and the second process can check .done files and delete the original file,since both .done and original file have same name but different extensions ?.
#Prashant's response gave me the inspiration for this, and it's very similar, but I believe will solve your problem.
If the other process must match a certain filename pattern
Rename the file to something that
won't match first, a very cheap/fast
operation
Rename it back when finished
If it matches every file in a given folder
Move it to another folder (also a very cheap operation in most filesystems)
Move it back when finished.
If the other process had already locked your file (even for read) then your process would fail, and you can make that graceful. If not you should be safe.
There is still a race condition possibility, of course, but this should be much safer than what you are doing.

How to detect programmatically what program caught my file

My program tries to write some data to a text file. But sometimes this file can be opened by some other program exclusively.
How to detect programmatically what program caught my file? I have to know user-friendly program name (here is my second question :)) that did it.
You detect it by the IOException you get when you try to open the file. This is a necessary evil on a multi-tasking operating system, there is no reliable way to implement a File.IsLocked() method. Windows doesn't have an API function for it. Because if such a function returns false, another process could interrupt your program and lock the file. When you get the cpu back, you'll find that the file is locked anyway. That's called a threading race.
So open the file with, say, the FileStream constructor. Pass FileShare.ReadWrite if you want to read from a file that's being written by another process. You have to allow ReadWrite sharing, the other process already gained the write access right. Catch the IOException you may get, you'll have to try again 'later'. Tell the user about it, she'll probably know what to do to help you. Like closing another program.
Btw, Windows does not provide any way to find out what other process has the file locked. There are utilities for that, like SysInterals' Handle utility. It grovels through undocumented internal kernel structures with a device driver that's dynamically installed. Nothing you'd want to tackle yourself.

Which WINAPI function I must use to know if a file is blocked by another process?

Which WINAPI function can I use to find out if a file has been opened by another process?
I use C# and sometimes get the exception "The process cannot access the file because it is being used by another process".
Simple try catch should do (catch specific exception though)... if you don't expect the file to be being used then it's ok to just handle the "exceptional" behavior.
In addition, try opening the file with the permissions you need, if you only need to read, open file for reading, another process might just be reading and that don't have to be a problem if you don't try to write it.
How about attempting to open the file exclusively inside a try/catch bloack and then trapping the file used by another process exception to check of the file is busy.

Categories