Is it possible to create a file using the FileStream object in .net, specifying DeleteAfterClose option and allow read access to that file?
I've tried using:
System.IO.FileStream strBMP = new System.IO.FileStream(sFileName, System.IO.FileMode.Create, System.Security.AccessControl.FileSystemRights., System.IO.FileShare.ReadWrite, 1024, System.IO.FileOptions.DeleteOnClose);
but the other object attempting the read gets a file share violation.
I'm trying to do this because I'm creating the file (a tif), and then using a COM object (MODI) to perform OCR on the image. My problem is that eve after I call the close method on the MODI com object, I still can't delete the file using the System.File.Delete method because the MODI com object hasn't quite finsished with it. I thought if I could create my file with the DeleteAfterClose option, and still allow reading on that file I'd be set, I just can't figure out how to get passed the sharing violation - if it is even possible.
When two processes are opening the same file, both of them need to specify compatible sets of file sharing flags for the second open to succeed. Unless you can control the flags being passed by MODI when it opens the file, there's probably no way to avoid the sharing violation; for example, if it attempts to open the file in an exclusive mode, it will always fail if your process has the file open, no matter what flags you pass to the FileStream constructor.
A well-designed COM object (which may or may not be the case here) would not leave files open when it was released, so the problem may be related to the .NET COM interop layer; it's possible that it's keeping some MODI COM objects alive in an unanticipated way. Indeed, threads on other forums about this problem all mention managed code. It's possible that some combination of Marshal.FinalReleaseComObject, GC.Collect, and GC.WaitForPendingFinalizers may help solve the problem, but no one appears to have written up a definitive solution (yet) and using those functions feels extremely hacky and very brittle.
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
I have a windows service and a desktop application running on the same machine. The app pre-processes some documents and transfers them to a folder where the service can take over. When the app is creating the new file for the service, it keeps a read-only lock on the file while writing. It them releases it so that the service can acquire a new read-only lock (FileStream).
I'd like the app to somehow hand-over this lock to the service without closing it. Is this possible in the managed runtime? If not, is there a way to P/Invoke this behaviour?
The reason this behaviour is desired is so that no other processes can modify or delete the file until both the app and service are done with it.
This is not possible in a managed-only way.
Try to use a simpler approach, such as naming the file with a random name in a temp directory such that no other application will try to open it.
If you insist on passing the handle, you must duplicate the handle into the service process and pass the numeric handle value of that process to the service process. Use OpenProcess, DuplicateHandle and CloseProcess for that.
From http://msdn.microsoft.com/en-us/library/windows/desktop/ms724251(v=vs.85).aspx:
The duplicate handle refers to the same object as the original handle.
Therefore, any changes to the object are reflected through both
handles. For example, if you duplicate a file handle, the current file
position is always the same for both handles. For file handles to have
different file positions, use the CreateFile function to create file
handles that share access to the same file.
I have many processes reading a file stored on a network share. Originally I was only able to have one process read the file, all the others would throw exceptions. I implemented the following code to deal with that:
using (StreamReader fileStreamReader = new StreamReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
content = fileStreamReader.ReadToEnd();
}
This let multiple processes read the same file, however it still seems to have issues, because sometimes multiple processes still can't access the file. Yet I can go back later when the file isn't in use and open it just fine. Right now I have some retry behavior with random delays implemented that so far, seem to help. It seems a little quirky to me to do it this way, so what would be a better method?
This is the weird part, the exception I'm getting is not from file IO at all, it's from a library called CommStudio. In short, I dump the file to a string, i modify it slightly, dump it into a memory stream, and ship it off over ymodem on rs232. The exception is telling me the remote system has canceled. The device getting the data reports that there was a transmission error, which usually means that an incomplete/empty file was received.
Normally I would blame the library on this, but it works flawlessly at desk-testing and when there is only one process accessing the file. The only thing that really seems to be consistent is that it is likely to fail when multiple processes are accessing a file.
had a similar problem but not allot of time to find an ideal solution. I created a webservice and stuck the file local to the webservice app.. then created a simple one liner GET API which was called over the office intranet.. thus ensureing only the calling application edited the log file.. messy but functional.
I have had a similar problem in the past. Try changing how you access the file to something like this.
//Use FileInfo to get around OS locking of the file
FileInfo fileInfo = new FileInfo(path);
//I actually wanted unblocked read write access so change your access and share appropriately
using (FileStream fs = fileInfo.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
{
//I'm using CopyTo but use whatever method matches your need
fileInfo.CopyTo(Path.Combine(destination, fileName), false);
}
I have a requirement to move certain files after they has been processed. Another process access the file and I am not sure when it releases them. Is there any way I can find out when the handle to the file has been released so I can move them at that time.
I am using Microsoft C# and .Net framework 3.5.
Cheers,
Hamid
If you have control of both the producer of the file and the consumer, the old trick to use is create the file under a different name, and rename it once complete.
For example, say the producer is creating files always called file_.txt, and your consumer is scanning for all files beginning file_, then the producer can do this:
1. Create the file called tmpfile_.txt
2. When the file is written, the producer simply renames the file to file_.txt
The rename operation is atomic, so once your consumer sees its available, it is safe to open it.
Of course, this answer depends on if you are writing both programs.
HTH
Dermot.
Just contniually try to open the file for exclusive writing? (e.g. pass FileShare.None to the FileStream constructor). Once you have opened it, you know no one else is using it. However, this might not be the best way to do what you're doing.
If you're after two way communication, see if the other program can be talked to via a pipe.
If you have control of both of the sources, use a named mutex (which works across processes) to control access to the files rather than locking the file at the filesystem level. This way, you don't have to catch the exception raised by attempting to lock a locked file and loop on that, which is rather inelegant.
I need to recover form an error case where a file gets left in a locked state. How can I in c# tell this file to reset it's locks? I need to add to this the file is opened by a 3rd party dll and I don't actually have access to the file handle.
Locking a file is the responsibility of the Operating System (on behalf of the program that opens it). If a file is left in a locked state, its really up to the OS to unlock. This typically happens automatically when the process that opened the file exits.
There is, however, a really cool utility that I came across that will help. It's called Unlocker.
You could perhaps start a command line process like net or psfile with something along the lines of:
System.Diagnostics.Process.Start("psfile c:\myfile.txt -c");
You can get psfile here.
You could also use
net file ID /close
but that would require you to know the file ID, which would take a bit more work.
Untested but this should give you a starting point.
I would really consider finding another 3rd party dll. Any system handling Streams should properly respond to error conditions and not leave things like file locks in place.
Is it possible that the library does provide error condition clean up, you've just over looked it? Try something like the following,
try {
thirdPartyObj = new ThirdPartObj();
// Some possible error causing object actions
catch(Exception ex) {
thirdPartyObj = null; // The object should close its resources
}
You have to close the file using .Close(). You need to make sure you still have a way of accessing the file object.
You usually can avoid this error by writing a try{} ... finally {} construct after the code that does your file I/O. In the finally {} block, you'd call the Close method of your file object, preventing this condition. You can also use a using {} block when you create your files, and this will also take care of this problem.