How can I determine if an IOException is caused by the fact that another process is using this file?

Take this code example:

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 is trying to overwrite) throws an exception:

 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() 

.. what is expected and obvious. HOWEVER , an instance of IOException does not offer me any reliable information that I can use programmatically to detect that a file is being used by another process. The Message property simply reports this, but it depends on the local culture, so I cannot rely on it.

Any ideas how to deal with this? I need to do a special action if the file is used by another process, but I canโ€™t find a way to separate this case from other (exceptional) cases.

+4
source share
2 answers

This question is possible for a duplicate of this , especially since the answer here is pretty close to accepted . However, there are some noticeable differences in the error codes to check. In the end, you might consider answering another question.

You can do as in this answer, but check 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, remember that using GetHRForException has side effects that you might not want.

Refresh . As @ jmn2 commentator noted, since .NET 4.5 is now the Exception.HResult property is open, so there is no need to use GetHRForException - unless you need support for version 4.5 code, of course.

To write a runtime compatible wrapper, you must call HResult through reflection, because (if you use GetProperties with BindingFlags.Public and BindingFlags.NonPublic ), which will work with all versions of .NET. (see this very important answer ).

+12
source

Here is a similar question

You will need to check HResult exceptions. Then check its value:

 int hr = Marshal.GetHRForException( ex ); 

Here is the code for the violation of the exchange of blocking violation

+1
source

All Articles