How to determine if an IOException is thrown due to an access violation?

I have a C # application and I want to copy the file to a new location. Several times I need to overwrite an existing file. When this happens, I get a System.IO.IOException message. I want to recover from a sharing violation, but how do I determine that an IOException has been returned because the target file is being used, and not some other reason? I could find "The process cannot access the file because it is being used by another process." message ... But I do not like this idea.

+6
source share
4 answers

This was the solution I came up with.

private void RobustMoveFile( System.IO.DirectoryInfo destinationDirectory, System.IO.FileInfo sourceFile, Boolean retryMove ) { try { string DestinationFile = Path.Combine( destinationDirectory.FullName, sourceFile.Name ); if ( File.Exists( DestinationFile ) ) sourceFile.Replace( DestinationFile, DestinationFile + "Back", true ); else { sourceFile.CopyTo( DestinationFile, true ); sourceFile.Delete(); } } catch ( System.IO.IOException IOEx ) { int HResult = System.Runtime.InteropServices.Marshal.GetHRForException( IOEx ); const int SharingViolation = 32; if ( ( HResult & 0xFFFF ) == SharingViolation && retryMove ) RobustMoveFile( destinationDirectory, sourceFile, false ); throw; } } 
+7
source share

As pointed out in other answers, you need to get HResult errors and check it out. HResult of 32 is a violation of sharing.

In .NET 4.5, an IOException has the public HResult property, so you can simply do the following:

 try { // do file IO here } catch (IOException e) { if (e.HResult == 32) // 32 = Sharing violation { // Recovery logic goes here } else { throw; // didn't need to catch this } } 

In earlier versions of .NET, you need to get HResult by calling Marshal.GetHRForException(Exception) , so similar code would look like this:

 try { // do file IO here } catch (IOException e) { int HResult = System.Runtime.InteropServices.Marshal.GetHRForException(e) if (HResult == 32) // 32 = Sharing violation { // Recovery logic goes here } else { throw; // Or do whatever else here } } 

While not yet released, C # 6.0 will, according to AC # 6.0 Language Preview , allow you to use this syntax to catch only an exchange violation:

 try { // do file IO here } catch (IOException e) if (e.HResult == 32) // 32 = Sharing violation { // Recovery logic goes here } 
+1
source share

Look for explicit error codes you may be dealing with, for example:

catch (Exception u) {if (((SocketException) u) .ErrorCode == 10035) ...

Take a look here: http://msdn.microsoft.com/en-us/library/ms681391(VS.85).aspx

for error codes, for example:

ERROR_SHARING_VIOLATION - 32 - 0x20

ERROR_ACCESS_DENIED = 5 - 0x5

ERROR_FILE_NOT_FOUND - 2 - 0x2

-one
source share

All Articles