Как определить HResult для системы.ИО.IOException?

Система.Исключение.Свойство HResult защищено. Как я могу заглянуть внутрь исключения и получить HResult, не прибегая к отражению или другим уродливым Хак?


ситуация такая:
Я хочу написать инструмент резервного копирования, который открывает и читает файлы в системе. Я открываю файл с помощью FileAccess.Чтение и файлообмен.ReadWrite, согласно данное руководство, потому что мне все равно, открыт ли файл для записи в то время, когда я его читаю.

в некоторых случаях, когда файл, который я читаю, открыт другим приложением, системой.ИО.FileStream.Метод Read () создает систему.ИО.IOException, "процесс не может получить доступ к файлу, потому что другой процесс заблокировал часть файла". Это ошибка 33, или Я думаю HResult 0x80070021. [редактировать: я считаю, что это может быть возвращено, когда другой процесс вызывает LockFileEx для блокировки диапазона байтов в файле.]

Я хотел бы сделать паузу и повторите попытку, когда я получу эту ошибку. Я думаю,что это подходящее решение. Если процесс блокировки быстро освобождает блокировку диапазона байтов, я могу продолжить чтение файла.

Как я могу отличить исключение IOException по этой причине от других? Я могу думать о таких способах:

  • личное отражение-не хочу этого делать. Перф будет вонять.
  • вызов исключения.ToString() и парсить строку. Чувствую себя избитым. Не будет работать в версиях i18n.

Мне не нравятся эти варианты. Разве нет лучшего, более чистого способа?


Я просто искал вокруг и нашел

5 ответов


для .Net Framework 4.5 и выше вы можете использовать Exception.HResult свойства:

int hr = ex.HResult;

для более старых версий, вы можете использовать Marshal.GetHRForException чтобы вернуть HResult, но это имеет значительные побочные эффекты и не рекомендуется:

int hr = Marshal.GetHRForException(ex);

чего бы это ни стоило,


вы также можете использовать ISerializable интерфейс:

static class IOExceptionExtensions
{
    public static int GetHResult(this IOException ex)
    {
        var info = new SerializationInfo(typeof (IOException), new FormatterConverter());
        ex.GetObjectData(info, new StreamingContext());
        return info.GetInt32("HResult");
    }
}

тут CanRead свойства помочь в этом случае?
то есть call CanRead, Если это возвращает true, вызов Read()


вы профилировали любой из этих случаев? Я бы предположил, что метод отражения не так уж медленен, особенно по отношению ко всем другим работам, которые будет делать ваше приложение, и как часто это исключение может произойти.

Если это окажется узким местом, вы можете изучить кэширование некоторых операций отражения или создать динамический IL для извлечения свойства.