Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine the HResult for a System.IO.IOException?

The System.Exception.HResult property is protected. How can I peek inside an exception and get the HResult without resorting to reflection or other ugly hacks?


Here's the situation:
I want to write a backup tool, which opens and reads files on a system. I open the file with FileAccess.Read and FileShare.ReadWrite, according to this guidance, because I don't care if the file is open for writing at the time I read it.

In some cases, when a file I am reading is open by another app, the System.IO.FileStream.Read() method throws a System.IO.IOException, "The process cannot access the file because another process has locked a portion of the file". This is error 33, or I think HResult 0x80070021. [EDIT: I believe this can be returned when another process calls LockFileEx to lock a byte range within a file.]

I'd like to pause and retry when I get this error. I think this is the appropriate action to take here. If the locking process releases the byte-range lock quickly, then I can proceed reading the file.

How can I distinguish an IOException for this reason, from others? I can think of these ways:

  • private reflection - don't wanna do that. Perf will stink.
  • call Exception.ToString() and parse the string. Feels hacky. Won't work in i18n versions.

I don't like these options. Isn't there a better, cleaner way?


I just searched around and found System.Runtime.InteropServices.Marshal.GetHRForException. Will that return a uint like 0x80070021?

like image 605
Cheeso Avatar asked Jun 13 '09 21:06

Cheeso


People also ask

How do you handle system IO IOException?

Handling IOException This means that it can be thrown by any I/O operation. Because IOException is the base class of the other exception types in the System.IO namespace, you should handle in a catch block after you've handled the other I/O-related exceptions.

What is a system IO IOException?

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.

Which of the following handles IO errors?

System.IO.IOException Handles I/O errors.

What is IO exception error?

IOException is usually a case in which the user inputs improper data into the program. This could be data types that the program can't handle or the name of a file that doesn't exist. When this happens, an exception (IOException) occurs telling the compiler that invalid input or invalid output has occurred.


2 Answers

For .Net Framework 4.5 and above, you can use the Exception.HResult property:

int hr = ex.HResult; 

For older versions, you can use Marshal.GetHRForException to get back the HResult, but this has significant side-effects and is not recommended:

int hr = Marshal.GetHRForException(ex); 
like image 85
JaredPar Avatar answered Oct 06 '22 10:10

JaredPar


For what it's worth, System.Exception.HResult is no longer protected in .NET 4.5 -- only the setter is protected. That doesn't help with code that might be compiled with more than one version of the framework.

like image 41
UweBaemayr Avatar answered Oct 06 '22 10:10

UweBaemayr