2

I was trying to make the below code work on .NET Standard 1.5, which implies it should be portable across all platforms .NET Standard 1.5 supports.

try
{
    channel = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
}
catch (IOException e) when ((e.HResult & 0xFFFF) == 0x00000020) // ERROR_SHARING_VIOLATION 
{
    // no failure reason to be recorded, since this is the expected error if a lock exists
}
catch (IOException e)
{
    FailureReason = e;
}
catch (UnauthorizedAccessException e)
{
    // On Windows, we can get intermittent "Access
    // Denied" here.  So, we treat this as failure to
    // acquire the lock, but, store the reason in case
    // there is in fact a real error case.
    FailureReason = e;
}

However, I have discovered when asking Does .NET Standard normalize HResult values across every platform it supports? that Exception.HResult cannot be used reliably across platforms. Now I am stuck.

What alternative to HResult is there for determining what type of exception was thrown when the .NET type is simply IOException? In other words, how do I reliably determine whether the error is a sharing violation (Windows: 0x00000020) or a lock violation (Windows: 0x00000021) so it can be distinguished from an IOException I am not interested in?

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • 1
    What prevents you from using `Environment.OSVersion` to figure out what OS you are running in and act upon any given `HResult` and OS accordingly? If you only have 2 or 3 codes you want to distinguish, it shouldn't be hard to manually figure out each one of them for all supported OS if there is not documentation available. – InBetween Sep 23 '17 at 18:52
  • In the other question, they pointed me to a Unix-specific class where those numbers are derived from a resource file. But, there are no corresponding files for the other platforms. I don't know where to look to get these numbers. Not even sure how I would determine if the OS is Android (`RuntimeInformation.IsOSPlatform()` doesn't have that option in its enumeration). .NET Standard is a moving target which may add more platforms in the future, as well (they have in the past few months added a few). Bottom line is that approach would not be reliable over the long run (as was implied by MS). – NightOwl888 Sep 23 '17 at 19:05

0 Answers0