Jak określić HResult dla System.IO. IOException?

System.Wyjątek.Własność HResult jest chroniona. Jak mogę zajrzeć do wyjątku i uzyskać HResult bez uciekania się do refleksji lub innych brzydkich hacków?


Oto sytuacja:
Chcę napisać narzędzie do tworzenia kopii zapasowych, które otwiera i odczytuje pliki w systemie. Otwieram plik za pomocą FileAccess.Czytaj i udostępniaj pliki.ReadWrite, zgodnie z tą instrukcją, ponieważ nie obchodzi mnie, czy plik jest otwarty do zapisu w momencie, gdy go czytam.

W niektórych przypadkach, gdy plik, który czytam, jest otwierany przez inną aplikację, Metoda System. IO. FileStream. Read () rzuca przypisanie System.IO.IOException, "proces nie może uzyskać dostępu do pliku, ponieważ inny proces zablokował część pliku". To jest błąd 33 , lub Myślę, że HResult 0x80070021. [EDIT : wierzę, że może to zostać zwrócone, gdy inny proces wywoła LockFileEx , aby zablokować zakres bajtów w pliku.]

Chciałbym zatrzymać i spróbować ponownie, gdy pojawi się ten błąd. Myślę, że jest to właściwe działania do podjęcia tutaj. Jeśli proces blokowania szybko zwolni blokadę zakresu bajtów, mogę kontynuować odczyt pliku.

Jak mogę z tego powodu odróżnić IOException od innych? Mogę myśleć o takich sposobach:

  • prywatna refleksja-nie chcę tego robić. Perf będzie śmierdzieć.
  • wyjątek wywołania.ToString () i parse the string. Czuję się chwiejny. Nie działa w wersjach i18n.

Nie lubię tych opcji. Czy nie ma lepszego, czystszego sposób?


Właśnie szukałem i znalazłem System.Runtime.InteropServices.Szeryfie.GetHRForException . Czy to zwróci uint jak 0x80070021?

Author: Community, 2009-06-14

5 answers

Dla. Net Framework 4.5 i nowszych, możesz użyć właściwości Exception.HResult:

int hr = ex.HResult;

W starszych wersjach można użyć Marshal.GetHRForException aby odzyskać HResult, ale to ma znaczące skutki uboczne i nie jest zalecane :

int hr = Marshal.GetHRForException(ex);
 54
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-01 19:52:08

Jeśli to coś warte, System.Wyjątek.HResult nie jest już chroniony w. NET 4.5-tylko setter jest chroniony. To nie pomaga w przypadku kodu, który może być skompilowany z więcej niż jedną wersją frameworka.

 11
Author: UweBaemayr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-03 18:15:15

Możesz również użyć interfejsu 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");
    }
}
 3
Author: Maxence,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-20 08:31:52

Czy CanRead property pomaga w tym przypadku?
tj. call CanRead, jeśli zwraca true, call Read()

 0
Author: shahkalpesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-13 21:44:29

Czy profilował Pan którąś z tych spraw? Wyobrażam sobie, że metoda odbicia nie jest zbyt powolna, zwłaszcza w stosunku do wszystkich innych prac, które Twoja aplikacja będzie robić i jak często ten wyjątek będzie prawdopodobnie występować.

Jeśli okaże się, że jest to wąskie gardło, możesz zajrzeć do buforowania niektórych operacji odbicia lub wygenerować dynamiczny IL, aby odzyskać właściwość.

 0
Author: Kevin Pullin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-13 21:49:57