簡體   English   中英

如何確定 System.IO.IOException 的 HResult?

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

System.Exception.HResult 屬性受到保護。 如何在不訴諸反射或其他丑陋黑客的情況下窺視異常並獲得 HResult?


這是情況:
我想編寫一個備份工具,它可以打開和讀取系統上的文件。 我根據本指南使用 FileAccess.Read 和 FileShare.ReadWrite 打開文件,因為我不關心文件在我閱讀時是否打開以進行寫入。

在某些情況下,當我正在讀取的文件被另一個應用程序打開時,System.IO.FileStream.Read() 方法會拋出 System.IO.IOException,“該進程無法訪問該文件,因為另一個進程已鎖定的一部分文件”。 這是錯誤 33 ,或者我認為 HResult 0x80070021。 [編輯:我相信當另一個進程調用LockFileEx以鎖定文件中的字節范圍時,可以返回此值。]

當我收到此錯誤時,我想暫停並重試。 我認為這是在這里采取的適當行動。 如果鎖定過程快速釋放字節范圍鎖定,那么我可以繼續讀取文件。

出於這個原因,我如何將 IOException 與其他異常區分開來? 我可以想到這些方法:

  • 私人反思 - 不想那樣做。 Perf 會發臭。
  • 調用 Exception.ToString() 並解析字符串。 感覺很雞肋。 不適用於 i18n 版本。

我不喜歡這些選項。 沒有更好、更清潔的方法嗎?


我只是四處搜索,發現System.Runtime.InteropServices.Marshal.GetHRForException 那會返回一個像 0x80070021 這樣的 uint 嗎?

對於 .Net Framework 4.5 及更高版本,您可以使用Exception.HResult屬性:

int hr = ex.HResult;

對於舊版本,您可以使用Marshal.GetHRForException來取回 HResult,但這具有顯着的副作用,不建議使用

int hr = Marshal.GetHRForException(ex);

就其價值而言, System.Exception.HResult在 .NET 4.5 中不再受保護——只有 setter 受到保護。 這對可能使用多個版本的框架編譯的代碼沒有幫助。

您還可以使用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");
    }
}

死靈法術。
或者您可以通過反射獲取受保護的屬性:

private static int GetHresult(System.Exception exception)
{
    int retValue = -666;

    try
    {
        System.Reflection.PropertyInfo piHR = typeof(System.Exception).GetProperty("HResult", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);

        if (piHR != null)
        {
            object o = piHR.GetValue(exception, null);
            retValue = System.Convert.ToInt32(o);
        }
    }
    catch (Exception ex)
    {
    }

    return retValue;
}

CanRead屬性在這種情況下有幫助嗎?
即調用CanRead ,如果返回 true,調用Read()

你有沒有分析過這些案例中的任何一個? 我想反射方法並不是那么慢,特別是相對於您的應用程序將要執行的所有其他工作以及此異常可能發生的頻率。

如果事實證明這是一個瓶頸,您可以考慮緩存一些反射操作或生成動態 IL 來檢索屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM