Let's take this code sample :
using System;
using System.IO;
namespace ConsoleApplication25
{
class Program
{
static void Main()
{
var bytes = new byte[] { 1, 2, 3 };
var trimChars = new[] { '"' };
var path = Environment.CommandLine.Trim().Trim(trimChars);
File.WriteAllBytes(path, bytes);
}
}
}
running this (the program tries to overwrite itself) causes an exception to be thrown :
System.IO.IOException was unhandled
Message=The process cannot access the file 'F:\TEMP\ConsoleApplication25\ConsoleApplication25\bin\Debug\ConsoleApplication25.vshost.exe' because it is being used by another process.
Source=mscorlib
StackTrace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at System.IO.File.WriteAllBytes(String path, Byte[] bytes)
at ConsoleApplication25.Program.Main() in F:\TEMP\ConsoleApplication25\ConsoleApplication25\Program.cs:line 13
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
.. which is expected and obvious. HOWEVER, the instance of the IOException doesn't offer me any reliable information that I can use programatically to detect that the file is in use by another process. Just the Message
property tells you this, but this depends on the local culture so I can't rely on it.
Any idea how to deal with this? I need to take a special action if the file is in use by another process but I can't find a way to separate this case from other (exceptional) cases.
First check if the file exists (File. Exists) if so try to open for write within try and catch block, if exception is generated then it is used by another process.
This can happen if the file referenced is open in another program or if a crash occurs while uploading. To resolve it, first make sure that no users have the file open anywhere, then reboot the machine to make sure it is not open as a remnant from a crash.
IOException is the base class for exceptions thrown while accessing information using streams, files and directories. The Base Class Library includes the following types, each of which is a derived class of IOException : DirectoryNotFoundException. EndOfStreamException. FileNotFoundException.
This question is possible a duplicate of this one, more so the answer here is pretty close to the accepted one. However, there is some notable difference about the error codes to check. You might consider, eventually, upvoting the answer to the other question.
You could do as in this answer, but check for ERROR_SHARING_VIOLATION
(0x20)
const long ERROR_SHARING_VIOLATION = 0x20;
const long ERROR_LOCK_VIOLATION = 0x21;
//Only for .NET <4.5: long win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
long win32ErrorCode = ex.HResult & 0xFFFF; // .NET 4.5+
if (win32ErrorCode == ERROR_SHARING_VIOLATION || win32ErrorCode == ERROR_LOCK_VIOLATION )
{
// file in use.
}
However, mind you that using GetHRForException
has side effects you may not want to have.
Update As commenter @jmn2 pointed out, since .NET 4.5 the Exception.HResult
property is now public. So there is no need for using GetHRForException
- unless you need to support pre 4.5 code, of course.
To write a "wrapper" that is runtime-backwards compatible you should invoke HResult
via reflection because (provided you use GetProperties
with BindingFlags.Public
and BindingFlags.NonPublic
) that will work with all versions of the .NET framework (see this very much related answer).
Here is similar question
You will need to check HResult of exception. And then check its value:
int hr = Marshal.GetHRForException( ex );
Here is code for sharing violation of lock violation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With