पूर्ण आंतरिक प्रदर्शन को प्रदर्शित करने का उचित तरीका क्या है?


155

मेरे पूर्ण दिखाने का उचित तरीका क्या है InnerException

मैंने पाया कि मेरे कुछ इनर एक्सिडेंस एक InnerExceptionऔर हैं और जो बहुत गहरे हैं।

InnerException.ToString()मेरे लिए काम करेंगे या क्या मुझे InnerExceptionsएक के Stringसाथ लूप बनाने और निर्माण करने की आवश्यकता है StringBuilder?


आपको आंतरिक अपवाद दिखाने की आवश्यकता क्यों है ??
अकरम शाहदा

26
@ अकरम क्योंकि अधिकांश समय यह आंतरिक अपवाद है जो दिलचस्प है। एक उदाहरण XmlSerializer है जो सिर्फ एक InvalidOperationException फेंकता है जब भी कुछ गलत होता है। जो गलत हुआ वह भीतरी अपवाद में है।
एड्रियनम ad

4
@AkramShahda खैर, हो सकता है कि आप अपने लॉगिंग में इस विधि का उपयोग करना चाहते हों?
cederlof

संबंधित पोस्ट - Exception.Message vs Exception.ToString ()
RBT

जवाबों:


239

आप बस प्रिंट कर सकते हैं exception.ToString()- जिसमें सभी नेस्टेड InnerExceptionएस के लिए पूर्ण पाठ भी शामिल होगा ।


18
यह भी अन्य बकवास का भार, न सिर्फ अपवाद संदेश और भीतरी अपवाद संदेश शामिल
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

सिर्फ सक्सेसनेस के लिए आपको वास्तव में .ToString () की आवश्यकता नहीं है, बस अपवाद का उपयोग करने से ऐसा ही होगा।
एलेक्स स्टीफेंस

3
@AlexStephens आप सही हैं, लेकिन केवल तभी यदि आपके पास किसी कारण के लिए "स्ट्रिंग टू" एक अंतर्निहित कास्टिंग है, जैसे कि पूर्ववर्ती स्ट्रिंग: "bla" + अपवाद
oo_dev

1
FYI करें: यह ToStringआंतरिक अपवादों के लिए कस्टम विधियों को कॉल क्यों नहीं करेगा जैसा कि System.Exception.ToString कॉल वर्चुअल ToString में आंतरिक अपवादों के लिए विस्तृत है?
जेफ बी

45

महज प्रयोग करें exception.ToString()

http://msdn.microsoft.com/en-us/library/system.exception.tostring.aspx

ToString का डिफ़ॉल्ट कार्यान्वयन उस वर्ग का नाम प्राप्त करता है जिसने वर्तमान अपवाद को फेंक दिया, संदेश, आंतरिक अपवाद पर ToString को कॉल करने का परिणाम, और Environment.StackTrace को कॉल करने का परिणाम। यदि इनमें से कोई भी सदस्य शून्य है, तो उसका मान लौटाए गए स्ट्रिंग में शामिल नहीं है।

यदि कोई त्रुटि संदेश नहीं है या यदि यह एक रिक्त स्ट्रिंग ("") है, तो कोई त्रुटि संदेश वापस नहीं आता है। आंतरिक अपवाद और स्टैक ट्रेस का नाम केवल तभी लौटाया जाता है जब वे अशक्त न हों।

अपवाद .oString () भी कॉल करेगा .ToString () उस अपवाद के आंतरिक अपवाद पर, और इसी तरह ...


45

मैं आमतौर पर शोर को दूर करने के लिए ऐसा करता हूं:

void LogException(Exception error) {
    Exception realerror = error;
    while (realerror.InnerException != null)
        realerror = realerror.InnerException;

    Console.WriteLine(realerror.ToString())
}    

संपादित करें: मैं इस जवाब के बारे में भूल गया और आश्चर्यचकित हूं कि किसी ने यह नहीं कहा कि आप बस कर सकते हैं

void LogException(Exception error) {
    Console.WriteLine(error.GetBaseException().ToString())
}    

यह विधि सबसे गहरे आंतरिक अपवाद को छोड़कर सब कुछ छुपाती है। यदि वह "शून्य से विभाजित" त्रुटि की तरह कुछ सांसारिक था, तो यह स्पष्ट नहीं होगा कि यह कहां हुआ और इससे क्या हुआ। जाहिर है, एक पूर्ण स्टैक ट्रेस आमतौर पर एक गन्दा ओवरकिल है, लेकिन केवल आंतरिक अपवाद को पढ़ना अन्य चरम है। user3016982 का जवाब कहीं बेहतर है। आपको बिना ट्रेस किए स्टैक में हर अपवाद संदेश मिलता है।
जेम्सहौक्स

1
@JamesHoux "user3016982" कौन सा उत्तर है? उसे यहां नहीं पा सकते।
मारकुजा-रस

User3016982 ThomazMoura है, देखें: stackoverflow.com/users/3016982/thomazmoura
Apfelkuacha

@JamesHoux, आंतरिक अपवाद में एक पूर्ण स्टैकट्रेस है जिसमें दिखाया गया है कि त्रुटि कहां हुई और इसके कारण क्या हुआ। समझ में नहीं आता कि स्टैक हटाए गए निशान से आपको कौन सी अतिरिक्त जानकारी मिलती है। अपवाद संदेश एक और बात है और यह उन सभी को इकट्ठा करने के लिए उपयोगी हो सकता है।
एड्रिनम

2
आप क्यों नहीं बस का उपयोग नहीं करते error.GetBaseException()। मेरा मानना ​​है कि यह वही करता है ...
रोबा

37

@ जॉन का जवाब सबसे अच्छा उपाय है जब आप पूर्ण विवरण (सभी संदेश और स्टैक ट्रेस) और अनुशंसित एक चाहते हैं।

हालाँकि, ऐसे मामले हो सकते हैं जब आप केवल आंतरिक संदेश चाहते हैं, और इन मामलों के लिए मैं निम्नलिखित एक्सटेंशन विधि का उपयोग करता हूं:

public static class ExceptionExtensions
{
    public static string GetFullMessage(this Exception ex)
    {
        return ex.InnerException == null 
             ? ex.Message 
             : ex.Message + " --> " + ex.InnerException.GetFullMessage();
    }
}

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


7
FYI करें, तो exएक है AggregateException, भीतरी अपवाद से कोई भी इस उत्पादन में शामिल किया जाएगा
kornman00

3
यह एक स्टॉक .NET विधि होना चाहिए। सभी को इसका उपयोग करना चाहिए।
जेम्सहौक्स

9

Messageगहरे अपवादों के सिर्फ एक हिस्से को ही प्रिंट करने के लिए , आप ऐसा कुछ कर सकते हैं:

public static string ToFormattedString(this Exception exception)
{
    IEnumerable<string> messages = exception
        .GetAllExceptions()
        .Where(e => !String.IsNullOrWhiteSpace(e.Message))
        .Select(e => e.Message.Trim());
    string flattened = String.Join(Environment.NewLine, messages); // <-- the separator here
    return flattened;
}

public static IEnumerable<Exception> GetAllExceptions(this Exception exception)
{
    yield return exception;

    if (exception is AggregateException aggrEx)
    {
        foreach (Exception innerEx in aggrEx.InnerExceptions.SelectMany(e => e.GetAllExceptions()))
        {
            yield return innerEx;
        }
    }
    else if (exception.InnerException != null)
    {
        foreach (Exception innerEx in exception.InnerException.GetAllExceptions())
        {
            yield return innerEx;
        }
    }
}

यह आवर्ती सभी अपवादों ( AggregateExceptionएस के मामले सहित ) के माध्यम से जाता Messageहै, उनमें निहित सभी संपत्ति को प्रिंट करने के लिए, लाइन ब्रेक द्वारा सीमांकित।

उदाहरण के लिए

var outerAggrEx = new AggregateException(
    "Outer aggr ex occurred.",
    new AggregateException("Inner aggr ex.", new FormatException("Number isn't in correct format.")),
    new IOException("Unauthorized file access.", new SecurityException("Not administrator.")));
Console.WriteLine(outerAggrEx.ToFormattedString());

बाहरी aggr पूर्व हुआ।
इनर एग्री।
नंबर सही प्रारूप में नहीं है।
अनधिकृत फ़ाइल का उपयोग।
प्रशासक नहीं।


आपको अधिक विवरण के लिए अन्य अपवाद गुणों को सुनने की आवश्यकता होगी । उदाहरण के लिए Dataकुछ जानकारी होगी। तुम यह कर सकते थे:

foreach (DictionaryEntry kvp in exception.Data)

सभी व्युत्पन्न गुण पाने के लिए (आधार Exceptionवर्ग पर नहीं ), आप कर सकते हैं:

exception
    .GetType()
    .GetProperties()
    .Where(p => p.CanRead)
    .Where(p => p.GetMethod.GetBaseDefinition().DeclaringType != typeof(Exception));

+1, यह लगभग वैसा ही है जैसा मैं करता हूं। अन्य समान प्रकारों को संभालने के लिए IEnumerable<Exception>हार्ड कोडिंग के बजाय एक संपत्ति के कार्यान्वयन के लिए विचार करें AggregrateException। इसके अलावा को बाहर p.IsSpecialNameऔर pi.GetIndexParameters().Length != 0समस्याओं से बचने के। आउटपुट में अपवाद प्रकार का नाम शामिल करना भी एक अच्छा विचार है
adrianm

संपत्ति की जाँच के बारे में @adrianm अच्छी बात है। अपवादों के संग्रह की जाँच के बारे में, यह सब है जहाँ आप रेखा खींचना चाहते हैं। यकीन है कि यह भी किया जा सकता है ..
nawfal

4

मैं करता हूँ:

namespace System {
  public static class ExtensionMethods {
    public static string FullMessage(this Exception ex) {
      if (ex is AggregateException aex) return aex.InnerExceptions.Aggregate("[ ", (total, next) => $"{total}[{next.FullMessage()}] ") + "]";
      var msg = ex.Message.Replace(", see inner exception.", "").Trim();
      var innerMsg = ex.InnerException?.FullMessage();
      if (innerMsg is object && innerMsg!=msg) msg = $"{msg} [ {innerMsg} ]";
      return msg;
    }
  }
}

यह "सुंदर प्रिंट" सभी आंतरिक अपवादों और एग्रीगेटएक्स अपवादों और उन मामलों को भी संभालता है जहां इनर एक्ससेप्शन। मेसेजेज इस संदेश के समान है


3

यदि आप सभी अपवादों के बारे में जानकारी चाहते हैं तो उपयोग करें exception.ToString()। यह सभी आंतरिक अपवादों से डेटा एकत्र करेगा।

यदि आप केवल मूल अपवाद चाहते हैं तो उपयोग करें exception.GetBaseException().ToString()। यह आपको पहला अपवाद मिलेगा, जैसे कि सबसे गहरा आंतरिक अपवाद या वर्तमान अपवाद यदि कोई आंतरिक अपवाद नहीं है।

उदाहरण:

try {
    Exception ex1 = new Exception( "Original" );
    Exception ex2 = new Exception( "Second", ex1 );
    Exception ex3 = new Exception( "Third", ex2 );
    throw ex3;
} catch( Exception ex ) {
    // ex => ex3
    Exception baseEx = ex.GetBaseException(); // => ex1
}

2

नवाफ के जवाब पर बिल्डअप।

उनके जवाब का उपयोग करते समय एक लापता चर aggrEx था, मैंने इसे जोड़ा।

फ़ाइल अपवाद: Exenstions.class:

// example usage:
// try{ ... } catch(Exception e) { MessageBox.Show(e.ToFormattedString()); }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YourNamespace
{
    public static class ExceptionExtensions
    {

        public static IEnumerable<Exception> GetAllExceptions(this Exception exception)
        {
            yield return exception;

            if (exception is AggregateException )
            {
                var aggrEx = exception as AggregateException;
                foreach (Exception innerEx in aggrEx.InnerExceptions.SelectMany(e => e.GetAllExceptions()))
                {
                    yield return innerEx;
                }
            }
            else if (exception.InnerException != null)
            {
                foreach (Exception innerEx in exception.InnerException.GetAllExceptions())
                {
                    yield return innerEx;
                }
            }
        }


        public static string ToFormattedString(this Exception exception)
        {
            IEnumerable<string> messages = exception
                .GetAllExceptions()
                .Where(e => !String.IsNullOrWhiteSpace(e.Message))
                .Select(exceptionPart => exceptionPart.Message.Trim() + "\r\n" + (exceptionPart.StackTrace!=null? exceptionPart.StackTrace.Trim():"") );
            string flattened = String.Join("\r\n\r\n", messages); // <-- the separator here
            return flattened;
        }
    }
}

मेरे पास एक अपवाद था क्योंकि:e.StackTrace == null
आंद्रेई कर्सुट्स्की

1
मैंने अद्यतन किया है। चयन (e => e.Message.Trim () + "\ r \ n \" + (e.StackTrace! = Null; StackTrace.Trim (): "")); शायद यह मदद करता है
शिमोन डूडकिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.