c# - मैं System.IO.IOException के लिए HResult कैसे निर्धारित करूं?




.net (4)

System.Exception.HResult संपत्ति संरक्षित है। मैं अपवाद के अंदर कैसे देख सकता हूं और एचआरएसल्ट को प्रतिबिंब या अन्य बदसूरत हैक्स का उपयोग किए बिना कैसे प्राप्त कर सकता हूं?

यहां स्थिति है:
मैं एक बैकअप उपकरण लिखना चाहता हूं, जो सिस्टम पर फ़ाइलों को खोलता है और पढ़ता है। मैं इस मार्गदर्शन के अनुसार FileAccess.Read और FileShare.ReadWrite के साथ फ़ाइल खोलता हूं, क्योंकि मुझे यह परवाह नहीं है कि फ़ाइल पढ़ने के समय फ़ाइल लिखने के लिए खुली है या नहीं।

कुछ मामलों में, जब मैं जो फ़ाइल पढ़ रहा हूं वह किसी अन्य ऐप द्वारा खुलती है, तो System.IO.FileStream.Read () विधि System.IO.IOException फेंकता है, "प्रक्रिया फ़ाइल तक नहीं पहुंच सकती है क्योंकि दूसरी प्रक्रिया ने एक हिस्से को लॉक कर दिया है फ़ाइल"। यह त्रुटि 33 है , या मुझे लगता है कि HResult 0x80070021। [ संपादित करें : मेरा मानना ​​है कि यह वापस लौटाया जा सकता है जब एक और प्रक्रिया LockFileEx को फ़ाइल के भीतर एक बाइट रेंज लॉक करने के लिए कॉल LockFileEx है।]

जब मैं यह त्रुटि प्राप्त करता हूं तो मैं रोकना और पुनः प्रयास करना चाहता हूं। मुझे लगता है कि यह यहां लेने के लिए उचित कार्रवाई है। यदि लॉकिंग प्रक्रिया बाइट-रेंज लॉक को तुरंत रिलीज़ करती है, तो मैं फ़ाइल को पढ़ना जारी रख सकता हूं।

मैं दूसरों से, इस कारण से IOException को अलग कैसे कर सकता हूं? मैं इन तरीकों से सोच सकता हूं:

  • निजी प्रतिबिंब - ऐसा नहीं करना चाहते हैं। पेर्फ डूब जाएगा।
  • अपवाद कॉल करें। ToString () और स्ट्रिंग पार्स। हैकी लगता है। I18n संस्करणों में काम नहीं करेगा।

मुझे इन विकल्पों को पसंद नहीं है। क्या कोई बेहतर, साफ रास्ता नहीं है?

मैंने अभी चारों ओर खोज की और System.Runtime.InteropServices.Marshal.GetHRForException पाया। System.Runtime.InteropServices.Marshal.GetHRForExceptionSystem.Runtime.InteropServices.Marshal.GetHRForException । क्या यह 0x80070021 की तरह एक संकेत वापस करेगा?


आप 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");
    }
}

इसके लायक होने के लिए, System.Exception.HResult अब .NET 4.5 में संरक्षित नहीं है - केवल सेटटर संरक्षित है। यह कोड के साथ मदद नहीं करता है जिसे ढांचे के एक से अधिक संस्करणों के साथ संकलित किया जा सकता है।


क्या इस मामले में संपत्ति की सहायता कर सकते हैं?
यानी CanRead कॉल करें, अगर यह सच हो जाता है, तो कॉल Read()


नेट फ्रेमवर्क 4.5 और ऊपर के लिए, आप Exception.HResult उपयोग कर सकते हैं। Exception.HResult संपत्ति:

int hr = ex.HResult;

पुराने संस्करणों के लिए, आप HResult वापस पाने के लिए मार्शल.GetHRForException का उपयोग कर सकते हैं, लेकिन इसका महत्वपूर्ण साइड इफेक्ट्स है और इसकी अनुशंसा नहीं की जाती है :

int hr = Marshal.GetHRForException(ex);





hresult