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:
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?
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);