Is there any way to check whether a file is locked without using a try catch block? Right now, the only way I know of is to just open the file and catch any System.IO.IOException.
No, unfortunately, and if you think about it, that information would be worthless anyway since the file could become locked the very next second (read: short timespan).
Why specifically do you need to know if the file is locked anyway? Knowing that might give us some other way of giving you good advice.
@lubos, Yes, but if you think about it, the information would be useless, except for reporting that at timeindex so and so, the file was locked or not.
If your code would look like this:
if not locked then
open and update file
Then between the two lines, another process could easily lock the file, giving you the same problem you were trying to avoid to begin with: exceptions.
That Windows Explorer takes forever to delete this file is different however, as Explorer enters a sleep-loop to see if the file becomes eligible for deletion within a given timeframe. Explorer itself is told immediately that the file cannot be deleted so that it hangs around for a while is purely in the design of that application.
I will venture that unless an operating system has a way to execute a piece of code in a transactional manner, no operating system will have this feature.
Then between the two lines, another process could easily lock the file, giving you the same problem you were trying to avoid to begin with: exceptions.
However, this way, you would know that the problem is temporary, and to retry later. (E.g., you could write a thread that, if encountering a lock while trying to write, keeps retrying until the lock is gone.)
The IOException, on the other hand, is not by itself specific enough that locking is the cause of the IO failure. There could be reasons that aren't temporary.
You can see if the file is locked by trying to read or lock it yourself first.
You could call LockFile via interop on the region of file you are interested in. This will not throw an exception, if it succeeds you will have a lock on that portion of the file (which is held by your process), that lock will be held until you call UnlockFile or your process dies.
Instead of using interop you can use the .NET FileStream class methods Lock and Unlock:
FileStream.Lock http://msdn.microsoft.com/en-us/library/system.io.filestream.lock.aspx
FileStream.Unlock http://msdn.microsoft.com/en-us/library/system.io.filestream.unlock.aspx
It's not necessarily worthless information. I'm automating some stuff with Word documents - I need to know when Word has closed and finished with the document - it holds a lock for the duration of the session. Word doesn't provide any other way to determine when it is done (there's a beforeClose event in the COM interop, but no Closed etc), and I can't check whether the process is running as it could be running with a different document. There is no concern that another process or word may grab the lock back after it is released.
When I'll faced with similar problem I finished with next code:
public class FileManager
{
private string _fileName;
private int _numberOfTries;
private int _timeIntervalBetweenTries;
private FileStream GetStream(FileAccess fileAccess)
{
var tries = 0;
while (true)
{
try
{
return File.Open(_fileName, FileMode.Open, fileAccess, Fileshare.None);
}
catch (IOException e)
{
if (!IsFileLocked(e))
throw;
if (++tries > _numberOfTries)
throw new MyCustomException("The file is locked too long: " + e.Message, e);
Thread.Sleep(_timeIntervalBetweenTries);
}
}
}
private static bool IsFileLocked(IOException exception)
{
int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);
return errorCode == 32 || errorCode == 33;
}
// other code
}