2009-06-24 9 views
13

सबसे पहले, समस्या: मेरे पास कई निःशुल्क प्रोजेक्ट हैं, और किसी भी सॉफ़्टवेयर में उनमें बग शामिल हैं। बग का सामना करते समय कुछ साथी उपयोगकर्ता मुझे स्टैक निशान के साथ एक बग-रिपोर्ट भेजते हैं। गलती की जगह ढूंढने को सरल बनाने के लिए, मैं इस स्टैक निशान में रेखा संख्या देखना चाहता हूं। यदि एप्लिकेशन .pdb फ़ाइलों के बिना भेज दिया गया है, तो सभी पंक्ति जानकारी खो जाती है, इसलिए वर्तमान में मेरी सभी परियोजनाएं .pdb फ़ाइलों के साथ तैनात हैं, और इसलिए जेनरेट किए गए स्टैक निशानों में यह संख्याएं हैं। लेकिन! लेकिन मैं इस फाइल को वितरण में नहीं देखना चाहता हूं और सभी .pdb को हटाना चाहता हूं। वे उन भ्रमित, संस्थापक में अंतरिक्ष, आदि.net में उपयोगकर्ता बग-रिपोर्ट से लाइन नंबरों के साथ स्टैक ट्रेस को मनोरंजन करें?

डेल्फी समाधान की खपत: अपने आवेदन की पैदल दूरी पर स्टैक पर अपवाद पर और पते इकट्ठा: बहुत समय पहले जब मैं एक डेल्फी प्रोग्रामर था, मैं निम्नलिखित तकनीक का इस्तेमाल किया। फिर, जब मुझे बग-रिपोर्ट प्राप्त होती है, तो मैंने एक उपकरण का उपयोग किया जो कि संग्रहित पते और मेरी मशीन पर स्थित संबंधित प्रतीक फ़ाइलों के आधार पर फ़ंक्शन नामों और रेखा संख्याओं के साथ वैध स्टैक ट्रेस का पुनर्निर्माण करता है।

प्रश्न: क्या कोई lib, या तकनीक है या .NET में जो कुछ भी करना है?

स्थिति अद्यतन: बहुत दिलचस्प है, जो अक्सर पूछताछ आपकी खुद की जांच शुरू करने का सबसे अच्छा तरीका है। उदाहरण के लिए मैं कुछ समय के लिए इस समस्या के बारे में सोचता हूं, लेकिन कई दिनों पहले ही उत्तर की तलाश करना शुरू कर देता हूं।

विकल्प 1: मिनीडंप। बहुत गुगलने के बाद मुझे कोड से मिनी डंप बनाने और प्रबंधित मिनी डंप से स्टैक को फिर से बनाने का तरीका मिला है। clrdump

  • ब्लॉग पिछले विधानसभा का उपयोग कर के बारे में पोस्ट - -

    हालांकि यह समाधान दो अतिरिक्त विधानसभाओं (~ आकार में 1MB) पुन: वितरित करने की जरूरत है, और मिनी डंप कुछ जगह लेता है, और उपयोगकर्ता को ईमेल द्वारा भेजने के लिए यह असहज है। तो मेरे उद्देश्यों के लिए, अभी, यह अस्वीकार्य है।

    विकल्प 2: सुराग के लिए weiqure धन्यवाद। प्रत्येक स्टैक फ्रेम के लिए प्रबंधित आईएल ऑफसेट निकालना संभव है। अब समस्या यह है कि इस ऑफ़सेट के आधार पर .pdb से लाइन नंबर कैसे प्राप्त करें। और मैं क्या पाया है:

    • PDB File Internals, बस जानकारी के लिए है क्योंकि:
    • ISymbolReader - कामयाब आसान xpath प्रसंस्करण

    इस का उपयोग के लिए कार्यक्रम डेटाबेस फ़ाइलों

  • और अंत में एक tool to convert .pdb files to structured xml पढ़ने के लिए इंटरफ़ेस टूल, प्रत्येक रिलीज बिल्ड के लिए एक्सएमएल फाइलें बनाना संभव है और उन्हें रिपोजिटरी में डाल दें। जब उपयोगकर्ता की मशीन पर अपवाद होता है, तो आईएल ऑफसेट के साथ स्वरूपित त्रुटि संदेश बनाना संभव है। फिर उपयोगकर्ता मेल द्वारा यह संदेश (बहुत छोटा) भेजता है। और आखिरकार, एक साधारण टूल बनाना संभव है जो स्वरूपित त्रुटि संदेश से परिणामी स्टैक को फिर से बनाएं।

    मुझे केवल आश्चर्य है कि क्यों कोई और इस तरह के उपकरण को लागू नहीं करता है? मुझे विश्वास नहीं है कि यह केवल मेरे लिए दिलचस्प है।

  • +0

    एफवाईआई: डेल्फी में यह अब आसान है क्योंकि पागलपन है जो एक स्टैक ट्रेस और अन्य उपयोगी सूचनाएं (अनचाहे) अपवादों पर एक रिपोर्ट में डालता है। – schnaader

    +1

    आपने किस विकल्प का चयन किया? मैं खुद भी समाधान की तलाश में हूं। – Giorgi

    +1

    मैंने दूसरा विकल्प चुना और आंतरिक अपवाद डंप को बदलने के लिए कक्षाओं का समूह लिखना चुना। मैं सभी जानकारी और स्रोतों के साथ अपने समाधान के बारे में एक लेख लिखने की भी योजना बना रहा हूं। – arbiter

    उत्तर

    2

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

    +0

    दिलचस्प लेख, लेकिन इसे पढ़ने के लिए अधिक समय की आवश्यकता है। और आम तौर पर यह ज्यादातर डिबगिंग (मनोरंजन ढेर नहीं) के लिए होता है, और उपयोगकर्ता से बहुत सी कार्रवाइयों की भी आवश्यकता होती है। – arbiter

    +0

    मैं सी # नेट से परिचित नहीं हूं, लेकिन WIN32 C++ अनुप्रयोगों में, मिनीडम्प ग्राहक साइट के मुद्दों का विश्लेषण करने के लिए बहुत प्रभावी हैं। मुझे लगता है कि सी # के लिए कुछ भी समान होना चाहिए। – Canopus

    +1

    मिनीडिंप मूल सी ++ कोड के लिए बहुत उपयोगी हैं। लेकिन मुझे एक मिनीडम्प फ़ाइल से .NET स्टैक ट्रेस को फिर से बनाने का कोई तरीका नहीं मिला है! – mmmmmmmm

    5

    आपको Environment.FailFast का उपयोग करना चाहिए, Application.UnhandledException में विफलता कॉल करें और आपके लिए एक डंप फ़ाइल बनाई जाएगी।

    MSDN से:

    failfast विधि विंडोज अनुप्रयोग ईवेंट लॉग संदेश पैरामीटर का उपयोग करने के लिए एक लॉग प्रविष्टि लिखते हैं, आपके आवेदन की एक डंप पैदा करता है, और उसके बाद वर्तमान प्रक्रिया समाप्त हो जाता है।

    failfast विधि यदि आपके आवेदन की स्थिति, मरम्मत के परे क्षतिग्रस्त और अपने आवेदन की कोशिश अंत में ब्लॉक और finalizers होगा भ्रष्ट कार्यक्रम संसाधनों को क्रियान्वित कर रहा है अपने आवेदन को समाप्त करने के बाहर निकलें विधि के बजाय का उपयोग करें। विफलता विधि वर्तमान प्रक्रिया को समाप्त करती है और क्रिटिकलफिनलाइज़र ऑब्जेक्ट ऑब्जेक्ट निष्पादित करती है, लेकिन कोई भी सक्रिय निष्पादित अंततः ब्लॉक या अंतिमकरण निष्पादित नहीं करता है।

    आप एक साधारण ऐप लिख सकते हैं जो लॉग फ़ाइलों को एकत्र करेगा और उन्हें आपको भेज देगा।

    अब, डंप फ़ाइल खोलना थोड़ा मुश्किल है, विजुअल स्टूडियो प्रबंधित डंप फ़ाइल (.NET 4.0 में तय) को संभाल नहीं सकता है, आप WinDBG का उपयोग कर सकते हैं लेकिन आपको SOS का उपयोग करने की आवश्यकता है।

    +3

    मेरी आवश्यकताओं के लिए कोई उपयुक्त नहीं: 1. अधिकांश अपवाद पुनर्प्राप्त करने योग्य हैं, इसलिए ऐप को जानकारी दिखाना चाहिए (वैकल्पिक रूप से इसे मेल पर भेजना) और जारी रखें। यह विधि ऐप को किसी भी अनचाहे अपवाद पर क्रश कर देगी। 2. इस विधि को मुझे अपवाद जानकारी भेजने के लिए उपयोगकर्ता से बहुत सी कार्रवाई की आवश्यकता है। लगभग कोई भी ऐसा नहीं करेगा। आप उपयोगकर्ताओं से उम्मीद कर सकते हैं कि वे त्रुटि संवाद से प्रतिलिपि की जानकारी कॉपी कर सकते हैं और इसे मेल द्वारा भेज सकते हैं, और नहीं। – arbiter

    12

    आप System.Diagnostics.StackTrace का उपयोग कर अपवाद से पिछले MSIL शिक्षा का ऑफसेट प्राप्त कर सकते हैं:

    // Using System.Diagnostics 
    static void Main(string[] args) 
    { 
        try { ThrowError(); } 
        catch (Exception e) 
        { 
         StackTrace st = new System.Diagnostics.StackTrace(e); 
         string stackTrace = ""; 
         foreach (StackFrame frame in st.GetFrames()) 
         { 
          stackTrace = "at " + frame.GetMethod().Module.Name + "." + 
           frame.GetMethod().ReflectedType.Name + "." 
           + frame.GetMethod().Name 
           + " (IL offset: 0x" + frame.GetILOffset().ToString("x") + ")\n" + stackTrace; 
         } 
         Console.Write(stackTrace); 
         Console.WriteLine("Message: " + e.Message); 
        } 
        Console.ReadLine(); 
    } 
    
    static void ThrowError() 
    { 
        DateTime myDateTime = new DateTime(); 
        myDateTime = new DateTime(2000, 5555555, 1); // won't work 
        Console.WriteLine(myDateTime.ToString()); 
    } 
    

    आउटपुट:

    ConsoleApplicationN.exe.Program.Main पर

    (IL ऑफसेट : 0x7) ConsoleApplicationN.exe.Program.ThrowError पर
    (IL ऑफसेट: 0x1b)
    mscorlib.dll.DateTime..ctor पर (IL ऑफसेट: 0x9)
    mscorlib.dll.Da पर teTime.DateToTicks (आईएल ऑफसेट: 0x61)
    संदेश: वर्ष, महीना, और दिन पैरामीटर एक गैर-प्रतिनिधित्व योग्य दिनांक का वर्णन करते हैं।

    फिर आप Reflector या ILSpy का उपयोग व्याख्या करने के लिए कर सकते हैं ऑफसेट:

    .method private hidebysig static void ThrowError() cil managed 
    { 
        .maxstack 4 
        .locals init (
         [0] valuetype [mscorlib]System.DateTime myDateTime) 
        L_0000: nop 
        L_0001: ldloca.s myDateTime 
        L_0003: initobj [mscorlib]System.DateTime 
        L_0009: ldloca.s myDateTime 
        L_000b: ldc.i4 0x7d0 
        L_0010: ldc.i4 0x54c563 
        L_0015: ldc.i4.1 
        L_0016: call instance void [mscorlib]System.DateTime::.ctor(int32, int32, int32) 
        L_001b: nop 
        L_001c: ldloca.s myDateTime 
        L_001e: constrained [mscorlib]System.DateTime 
        L_0024: callvirt instance string [mscorlib]System.Object::ToString() 
        L_0029: call void [mscorlib]System.Console::WriteLine(string) 
        L_002e: nop 
        L_002f: ret 
    } 
    

    तुम्हें पता है कि 0x1b से पहले निर्देश अपवाद फेंक दिया। ऐसा नहीं है कि के लिए सी # कोड को खोजने के लिए आसान है:

    myDateTime = new DateTime(2000, 5555555, 1); 
    

    अब आप अपने सी # कोड के लिए आईएल कोड मैप कर सकते हैं, लेकिन मुझे लगता है कि लाभ बहुत कम हो जाएगा और प्रयास बहुत बड़े हैं (हालांकि वहाँ एक परावर्तक हो सकता है लगाना)। आपको आईएल ऑफ़सेट के साथ ठीक होना चाहिए।

    +0

    मुझे आपका विचार पसंद है, और आपका जवाब ऊपर उठाया है, लेकिन यह केवल मसौदा विचार है। हो सकता है कि कुछ विधि, या जानकारी इस आईएल ऑफसेट को संबंधित .pdb फ़ाइल में मैप करने के लिए कैसे करें (क्योंकि प्रोजेक्ट में कई असेंबली हैं, और प्रत्येक असेंबली के पास यह है .pdb)। – arbiter

    +0

    यदि आपने आईएल कोड को .pdb फ़ाइलों या सी # कोड में मैप करने के बारे में एक और सवाल पूछा है तो यह शायद सबसे अच्छा होगा। हालांकि, जैसा कि मैंने कहा था, मुझे यकीन नहीं है कि यह मैन्युअल रूप से करने से आसान होगा। – weiqure

    +0

    वॉच विंडो के लिए: नई प्रणाली। डायग्नोस्टिक्स.स्टैकट्रेस ($ अपवाद) .GetFrames() [0] .ILOffset – zproxy

    1

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

    माइक्रोसॉफ्ट सिंबल सर्वर डिबग प्रतीकों को इंडेक्स करेगा और बाद में उपयोग के लिए उन्हें स्टोर करेगा जब आपके पास क्रैश डंप होगा, उदाहरण के लिए, और प्रतीकों को उपलब्ध होना चाहिए। आप विजुअल स्टूडियो या विंडबग को अपने स्वयं के प्रतीक सर्वर इंस्टेंस पर इंगित कर सकते हैं, जैसे कि Microsoft's, और यह आपके एप्लिकेशन के उस संस्करण को डिबगिंग के लिए जरूरी प्रतीकों को खींच देगा (माना जाता है कि आप शिपिंग से पहले प्रतीक सर्वर के साथ प्रतीकों को अनुक्रमित करते हैं)।

    एक बार आपके पास निर्माण के लिए उचित प्रतीक होने के बाद, आपको यह सुनिश्चित करना होगा कि आपके पास उस उचित स्रोत फाइलें हैं जो निर्माण के हैं।

    यह जहां माइक्रोसॉफ्ट स्रोत सर्वर में आता है। बस जहां प्रतीक सर्वर अनुक्रमित प्रतीकों, स्रोत सर्वर सूचकांक स्रोत सुनिश्चित करें कि आप एक सॉफ्टवेयर निर्माण से संबंधित स्रोत कोड के उचित संस्करण है बनाने के लिए होगा की तरह है। संस्करण नियंत्रण, प्रतीक सर्वर और स्रोत सर्वर की

    कार्य संस्करणों अपने सॉफ्टवेयर विन्यास प्रबंधन रणनीति का हिस्सा होना चाहिए।

    तीसरे पक्ष के उपकरण हैं, कुछ वाणिज्यिक, जो आपको एप्लिकेशन स्नैपशॉट जेनरेट करने के लिए एक एपीआई प्रदान करेंगे, लेकिन जैसा कि आप पहले ही समझ चुके हैं, आपको किसी भी तरह से अपने स्नैपशॉट्स को अपलोड करने के लिए एक तंत्र की आवश्यकता है।

    जॉन पर PDB Files

    जॉन रॉबिंस पर एक प्रतीक सर्वर को ठीक और चालू पर Source Server

    चेक बाहर WinDbg documentation रॉबिंस।

    संबंधित मुद्दे