2013-05-08 5 views
10

द्वारा पकड़ा नहीं गया पृष्ठभूमि पृष्ठभूमि में, मेरा आवेदन नियमित रूप से एप्लिकेशन अपडेट के लिए नेटवर्क फ़ोल्डर (यूएनसी पथ) की जांच करता है। यह फ़ाइल की विधानसभा संस्करण को पढ़ता है, इसलिए जैसे:SEHException कोशिश/कैच

Try 
    newVers = System.Reflection.AssemblyName.GetAssemblyName("\\server\app.exe").Version 
Catch ex As Exception 
    ' ignore 
End Try 

यह स्निपेट अक्सर निष्पादित किया जाता है, कुल में मैं अब तक एक समस्या के बिना एक से अधिक ग्राहक साइटों पर जिस तरह से 100,000 से अधिक बार लगता है कि चाहते हैं।

कभी-कभी, GetAssemblyNameFileNotFoundException बढ़ाता है, उदाहरण के लिए यदि नेटवर्क फ़ोल्डर पहुंच योग्य नहीं है (जो हो सकता है और इसके साथ निपटा जाना चाहिए)। यह अपवाद Catch ब्लॉक से नीचे पकड़ा गया है, और सब कुछ ठीक काम करता है।

तीन रिपोर्ट किए गए मामलों में, GetAssemblyName कॉल ने SEHException उठाया। अजीब बात यह है कि इस अपवाद को नीचे Catch ब्लॉक द्वारा पकड़ा नहीं गया था, लेकिन मेरे वैश्विक अनचाहे अपवाद हैंडलर (System.AppDomain.CurrentDomain.UnhandledException) द्वारा। नतीजतन, आवेदन दुर्घटनाग्रस्त हो जाता है।

यहाँ अपवाद विस्तार (दुर्भाग्य से, अपवाद के ErrorCode और CanResume क्षेत्रों मेरी त्रुटि दिनचर्या से निपटने से लॉग इन नहीं हैं) है:

Caught exception: System.Runtime.InteropServices.SEHException 
    Message: External component has thrown an exception. 
    Source: mscorlib 
    TargetSite: System.Reflection.AssemblyName nGetFileInformation(System.String) 
    StackTrace: 
     at System.Reflection.AssemblyName.nGetFileInformation(String s) 
     at System.Reflection.AssemblyName.GetAssemblyName(String assemblyFile) 
     at SyncThread.Run() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 

क्यों है कि अपवाद Catch ब्लॉक द्वारा पकड़ा नहीं है ठीक नीचे?

(हो सकता है कि यह प्रासंगिक है: यह केवल ग्राहक साइटों, जहां यूएनसी पथ एक सर्वर है कि स्थानीय नेटवर्क का हिस्सा नहीं था की ओर इशारा किया पर हुआ है, लेकिन एक वीपीएन पर एक दूरस्थ सर्वर।)

+0

हमारे मामले में, हम टेलीरिक रैडग्रिड व्यू का उपयोग कर रहे हैं और एक पंक्ति जोड़ने के दौरान कभी-कभी इनमें से एक प्राप्त करते हैं। मेरे पास एक ही सवाल था कि यह क्यों पकड़ा नहीं जाएगा। एंड्रियास के सवाल के लिए धन्यवाद, और उत्तर @porges के लिए धन्यवाद। – ebol2000

उत्तर

12

के बाद से। नेट 4, कुछ SEHException एस दूषित प्रक्रिया राज्यों को इंगित करता है, और इसे "दूषित राज्य अपवाद" कहा जाता है। ये segfaults/पहुंच उल्लंघनों जैसी चीजें हैं, जहां स्मृति भ्रष्टाचार का पता चला है के बाद अपवाद फेंक दिया गया है।

हालांकि इन त्रुटियों को अभी भी प्रबंधित किया गया है .NET SEHExceptions, वे डिफ़ॉल्ट रूप से सक्षम नहीं हैं, इसलिए try { ... } catch (Exception ex) { ... } उन्हें संभाल नहीं पाएंगे।

आप में शामिल हो सकते लेकिन इसके कुछ अपवाद हैंडलिंग (या तो via an attribute or a policy change in your app's config file) करने के लिए, लेकिन यह अनुशंसित नहीं है, के रूप में अपने कार्यक्रम अब प्रसंस्करण अमान्य डेटा हो सकता है:

CLR हमेशा जन्म दिया है SEH प्रबंधित कोड के लिए अपवाद प्रोग्राम द्वारा उठाए गए अपवादों के समान तंत्र का उपयोग करना। यह तब तक कोई समस्या नहीं है जब तक कोड असाधारण स्थितियों को संभालने का प्रयास नहीं करता है, जिसे उचित रूप से संभाल नहीं सकता है। अधिकांश उल्लंघन एक्सेस उल्लंघन के बाद निष्पादन को सुरक्षित रूप से जारी नहीं रख सकते हैं। दुर्भाग्यवश, सीएलआर के अपवाद हैंडलिंग मॉडल ने हमेशा उपयोगकर्ताओं को सिस्टम के शीर्ष पर किसी अपवाद को पकड़ने की अनुमति देकर इन गंभीर त्रुटियों को पकड़ने के लिए प्रोत्साहित किया है। अपवाद पदानुक्रम। लेकिन यह शायद ही कभी सही काम है।

लेखन पकड़ (अपवाद ई) एक सामान्य प्रोग्रामिंग त्रुटि है क्योंकि अनचाहे अपवादों के गंभीर परिणाम हैं। लेकिन आप तर्क दे सकते हैं कि यदि आपको नहीं पता कि किसी फ़ंक्शन द्वारा कौन सी त्रुटियां उठाई जाएंगी, तो आपको उस प्रोग्राम को कॉल करने पर सभी संभावित त्रुटियों से रक्षा करनी चाहिए। यह तब तक कार्रवाई के उचित तरीके की तरह प्रतीत होता है जब तक आप सोचते हैं कि निष्पादन जारी रखने का क्या अर्थ है जब आपकी प्रक्रिया संभवतः दूषित स्थिति में होती है। कभी-कभी निरस्त करना और फिर से प्रयास करना सबसे अच्छा विकल्प है: कोई भी वॉटसन संवाद नहीं देखना पसंद करता है, लेकिन आपके डेटा को दूषित करने के बजाय अपने प्रोग्राम को पुनरारंभ करना बेहतर होता है।

उन संदर्भों से उत्पन्न अपवादों को पकड़ने वाले कार्यक्रम जो वे समझ में नहीं आते हैं, एक गंभीर समस्या है। लेकिन आप अपवाद विनिर्देशों या कुछ अन्य अनुबंध तंत्र का उपयोग करके समस्या का समाधान नहीं कर सकते हैं। और यह महत्वपूर्ण है कि प्रबंधित प्रोग्राम एसईएच अपवादों की अधिसूचना प्राप्त करने में सक्षम हों क्योंकि सीएलआर कई प्रकार के अनुप्रयोगों और मेजबानों के लिए एक मंच है। कुछ होस्ट, जैसे कि SQL सर्वर, को उनके अनुप्रयोग की प्रक्रिया का पूर्ण नियंत्रण होना चाहिए। प्रबंधित कोड जो देशी कोड के साथ इंटरऑपरेट करता है कभी-कभी देशी सी ++ अपवाद या एसईएच अपवादों से निपटना चाहिए।

लेकिन अधिकांश प्रोग्रामर जो पकड़ (अपवाद ई) लिखते हैं, वास्तव में पहुंच उल्लंघन को पकड़ना नहीं चाहते हैं। वे चाहते हैं कि उनके प्रोग्राम का निष्पादन तब बंद हो जाए जब किसी अज्ञात स्थिति में प्रोग्राम को लम्बाई देने के बजाए एक विनाशकारी त्रुटि होती है। यह उन कार्यक्रमों के लिए विशेष रूप से सच है जो विजुअल स्टूडियो या माइक्रोसॉफ्ट ऑफिस जैसे प्रबंधित ऐड-इन्स होस्ट करते हैं। यदि कोई ऐड-इन एक्सेस उल्लंघन का कारण बनता है और फिर अपवाद को निगलता है, तो होस्ट कभी भी कुछ गलत होने के बिना अपने राज्य (या उपयोगकर्ता फ़ाइलों) को नुकसान पहुंचा सकता है।

The article this quote is from (in MSDN magazine) अधिक जानकारी में चला जाता है।

यदि आप इन अपवादों को संभालने का निर्णय लेते हैं, तो इस पर विचार करने के लिए बहुत कुछ है - जैसा कि लेख कहता है "सीएसई को संभालने वाले सही कोड को लिखना बहुत मुश्किल है और प्रक्रिया को सुरक्षित रूप से चलाना जारी रखता है।"

विशेष रूप से, किसी भी finally ब्लॉक अपवाद से अधिक निष्पादित नहीं किया गया (हां, जैसे किसी भी फ़ाइल हैंडल जब तक एकत्र झूलते रहे हैं) है पारित किया है कि, और यहां तक ​​कि constrained execution regions छोड़ी नहीं जा सकती!


इसके अलावा, आप शायद इस माइक्रोसॉफ्ट के लिए एक बग के रूप में रिपोर्ट करना चाहिए, के रूप में GetAssemblyName अपवाद इस तरह फेंक नहीं किया जाना चाहिए।

+0

तो सिस्टम कैसे कर सकते हैं। Reflection.AssemblyName.GetAssembly नाम स्मृति को दूषित करता है? – Andreas

+0

@ एंड्रियास: मैंने अंत में एक नोट जोड़ा लेकिन आप बहुत जल्दी थे! यह एक बग की तरह दिखता है, इसे कभी नहीं करना चाहिए। – porges