2009-06-13 11 views
33

सिस्टम। अपवाद। HResult संपत्ति संरक्षित है। मैं अपवाद के अंदर कैसे देख सकता हूं और एचआरएसल्ट को प्रतिबिंब या अन्य बदसूरत हैक्स का उपयोग किए बिना कैसे प्राप्त कर सकता हूं?
मैं एक बैकअप उपकरण है, जो खोलता है और एक प्रणाली पर फ़ाइलें पढ़ता लिखना चाहते हैं:मैं System.IO.IOException के लिए HResult कैसे निर्धारित करूं?


यहाँ की स्थिति है। this guidance के अनुसार, मैं FileAccess.Read और FileShare.ReadWrite के साथ फ़ाइल खोलता हूं, क्योंकि मुझे यह परवाह नहीं है कि फ़ाइल पढ़ने के समय फ़ाइल के लिए खुला है या नहीं।

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

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

मैं इस कारण से किसी अन्य कारण से IOException को कैसे अलग कर सकता हूं? मैं इन तरीकों के बारे में सोच सकता हूं:

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

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


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

+3

> निजी प्रतिबिंब - ऐसा नहीं है चाहता हूँ। पेर्फ डूब जाएगा। - अपवाद perf वैसे भी बदबू आ रही है, तो मैं perf पहलू के बारे में चिंता नहीं होगी। प्रतिबिंब करता है - हालांकि - पूर्ण ट्रस्ट की आवश्यकता है, बदसूरत है, और असमर्थित है और टूटने के लिए प्रवण है - यही कारण है कि आपको यह नहीं करना चाहिए। –

उत्तर

54

.Net Framework 4.5 और इसके बाद के संस्करण के लिए, आप Exception.HResult संपत्ति का उपयोग कर सकते हैं:

int hr = ex.HResult; 

पुराने संस्करणों के लिए, आप Marshal.GetHRForException उपयोग कर सकते हैं HRESULT वापस पाने के लिए, लेकिन इस has significant side-effects and is not recommended:

int hr = Marshal.GetHRForException(ex); 
+0

बहुत बहुत धन्यवाद! यह वास्तव में सी #/COM इंटरऑपरेबिलिटी के मामले में विकास को कम करता है। – rds

+2

+1 ओह, पूर्ण विश्वास की आवश्यकता है ... लेकिन फिर भी यह एक समाधान है। – reSPAWNed

+3

दुष्प्रभावों से सावधान रहें: "ध्यान दें कि ** GetHRForException ** विधि वर्तमान थ्रेड के ** IErrorInfo ** सेट करता है। इससे ** ThrowExceptionForHR ** विधियों जैसे विधियों के लिए अप्रत्याशित परिणाम हो सकते हैं जो डिफ़ॉल्ट रूप से उपयोग करने के लिए डिफ़ॉल्ट हैं वर्तमान थ्रेड के ** IErrorInfo ** सेट होने पर। " – HugoRune

0

CanRead संपत्ति इस मामले में मदद करता है?
अर्थात, CanRead फोन है कि अगर सच देता है, फोन Read()

+0

नहीं, CanRead सच है। मेरा मानना ​​है कि 80070021 एक क्षणिक त्रुटि है। यदि मैं सही ढंग से दस्तावेज़ पढ़ रहा हूं, इसे संभालने के लिए अनुशंसित अभ्यास "थोड़ी देर प्रतीक्षा करें और पुनः प्रयास करें।" – Cheeso

+0

क्या यह संभव है कि आपने फ़ाइल को पढ़ने के लिए खोला और किसी और ने इसे भी खोला (FileShare.Read का उपयोग करके), पहला कॉलर अब और नहीं पढ़ सकता है? क्या आप क्षणिक से क्या मतलब है? – shahkalpesh

+0

नहीं, मेरा मतलब यह है कि फ़ाइल के भीतर एक सीमा को लॉक करने के लिए फ़ाइल पर फ़ाइल लॉक या फ़ाइल लॉकएक्स (http://msdn.microsoft.com/en-us/library/aa365203.aspx) कहा जाता है। इसे कभी-कभी बाइट-रेंज लॉक कहा जाता है। किसी बिंदु पर लॉकिंग प्रक्रिया रेंज लॉक जारी करेगी। मेरा मतलब है "क्षणिक"। – Cheeso

0

आप इनमें से किसी दशा प्रोफाइल है? मैं कल्पना करता हूं कि प्रतिबिंब विधि धीमी नहीं है, विशेष रूप से आपके अन्य ऐप के अन्य सभी कार्यों के सापेक्ष और यह अपवाद कितनी बार होने की संभावना है।

यदि यह एक बाधा बन जाती है तो आप कुछ प्रतिबिंब संचालन को कैशिंग में देख सकते हैं या संपत्ति को पुनर्प्राप्त करने के लिए गतिशील आईएल उत्पन्न कर सकते हैं।

11

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

3

तुम भी 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"); 
    } 
} 
संबंधित मुद्दे