2009-05-08 14 views
15

में ब्रेकपॉइंट्स को प्रोग्रामेटिक रूप से लागू/निष्क्रिय करना एक ही परिणाम प्राप्त करने वाले अन्य विकल्पों के बावजूद (यानी ब्रेकपॉइंट्स हाथ से जोड़ना), क्या प्रोग्राम स्टूडियो प्रोजेक्ट के स्रोत कोड में प्रोग्रामेटिक रूप से ब्रेकपॉइंट जोड़ना संभव है?विजुअल स्टूडियो

जैसे:

try 
{ 
    FunctionThatThrowsErrors(obj InscrutableParameters); 
} 
catch(Exception ex) 
{ 
    Log.LogTheError(ex); 
    AddBreakPointToCallingFunction(); 
} 

इस तरह जब आप अगली बार डिबग में चलाने के लिए, यह स्वचालित रूप से breakpoints सभी बिंदुओं कि पिछले चलाने के दौरान परेशानी का कारण बना पर निर्धारित किये गये होगा।

मैं यह नहीं कह रहा हूं कि यह डिबगिंग का एक विशेष रूप से उपयोगी तरीका है। मैं बस सोच रहा हूं कि क्या क्षमता है।

+0

यह होना चाहिए, मैं इसे ++ (IsDebuggerPresent()) डीबगब्रैक() के माध्यम से हर समय C++ में करता हूं; ', मेरे पास यह मेरे कई अपवाद वर्गों के निर्माता में है। –

उत्तर

39

आपने मुझे इस के साथ घूमने के लिए प्रेरित किया - मुझे पूरी रात जागने के लिए धन्यवाद। :) यहां एक तरीका है कि आप इसे कर सकते हैं।

विजुअल स्टूडियो वास्तव में बहुत अच्छा ब्रेकपॉइंट समर्थन है। कूलर फीचर्स में से एक यह है कि ब्रेकपॉइंट हिट होने पर आप इसे विजुअल स्टूडियो मैक्रो चलाने के लिए कह सकते हैं। इन मैक्रोज़ के पास विकास पर्यावरण तक पूर्ण पहुंच है, यानी वे अन्य ब्रेकपॉइंट्स सेट करने सहित कीबोर्ड पर मैन्युअल रूप से जो भी कर सकते हैं, कर सकते हैं।

यह समाधान 1 है) सभी अपवादों को पकड़ने के लिए अपने कार्यक्रम में शीर्ष-स्तरीय प्रयास/पकड़ डालें, 2) अपने मैक्रो को चलाने वाले कैच ब्लॉक में ब्रेकपॉइंट डालें, और 3) अपवाद पर मैक्रो देखें यह पता लगाने के लिए कि यह कहां से आया था, और वहां एक ब्रेकपॉइंट लगाया। जब आप इसे डीबगर में चलाते हैं और अपवाद होता है, तो आपके पास कोड की अपमानजनक रेखा पर एक नया ब्रेकपॉइंट होगा।

इस नमूने कार्यक्रम लें:

using System; 

namespace ExceptionCallstack 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       func1(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("Oops"); 
       Console.ReadKey(); 
      } 
     } 

     static void func1() 
     { 
      func2(); 
     } 

     static void func2() 
     { 
      func3(); 
     } 

     static void func3() 
     { 
      throw new Exception("Boom!"); 
     } 
    } 
} 

उद्देश्य प्रोग्राम के रूप में func3 में है कि throw पर एक ब्रेकपाइंट सेट करने के लिए जब आप डीबगर में इसे चलाने और त्रुटि मिलती है। ऐसा करने के लिए, पहले एक नया विजुअल स्टूडियो मैक्रो बनाएं (मैंने मेरा सेटब्रेकपॉइंटऑनएक्सप्शन कहा है)। एक नए मॉड्यूल MyDebuggerMacros या जो कुछ भी पर पेस्ट करें:

Imports System 
Imports EnvDTE 
Imports EnvDTE80 
Imports EnvDTE90 
Imports System.Diagnostics 
Imports System.Text.RegularExpressions 

Public Module DebuggerMacros 

    Sub SetBreakpointOnException() 

     Dim output As String = "" 

     Dim stackTrace As String = DTE.Debugger.GetExpression("e.StackTrace").Value 
     stackTrace = stackTrace.Trim(New Char() {""""c}) 
     Dim stackFrames As String() = Regex.Split(stackTrace, "\\r\\n") 

     Dim r As New Regex("^\s+at .* in (?<file>.+):line (?<line>\d+)$", RegexOptions.Multiline) 
     Dim match As Match = r.Match(stackFrames(0)) 
     Dim file As String = match.Groups("file").Value 
     Dim line As Integer = Integer.Parse(match.Groups("line").Value) 

     DTE.Debugger.Breakpoints.Add("", file, line) 

    End Sub 

End Module 

एक बार यह मैक्रो जगह में है, वापस catch ब्लॉक करने के लिए जाने के लिए और F9 के साथ एक ब्रेकपाइंट निर्धारित किया है। फिर लाल ब्रेकपॉइंट सर्कल पर राइट-क्लिक करें और "जब हिट करें ..." चुनें। परिणामी संवाद के निचले हिस्से में मैक्रो चलाने के लिए इसे बताने का एक विकल्प है - सूची को छोड़ दें और अपना मैक्रो चुनें। अब जब आपका ऐप अनचाहे अपवाद फेंकता है तो आपको नए ब्रेकपॉइंट प्राप्त करना चाहिए।

नोट्स और प्रतिवाद इस बारे में:

  • मैं नहीं एक regex गुरु हूँ, मुझे यकीन है कि किसी और को कुछ बेहतर कोड़ा सकता हूँ।
  • यह नेस्टेड अपवादों (इनर एक्सेप्शन प्रॉपर्टी) को संभाल नहीं करता है - यदि आप चाहें तो इसके खिलाफ अपने सिर को हरा सकते हैं। :) GetExpression ("e.InnerException") के लिए जांचें और शायद रिकर्स करें।
  • यह उत्तेजना की स्टैकट्रेस स्ट्रिंग पर पाठ पार्सिंग करता है, अधिक परिष्कृत ऑब्जेक्ट ग्राफ़ विश्लेषण नहीं (अपवाद में खोदना। लक्ष्यसाइट और प्रतिबिंब का उपयोग करना)। सामान्य चेतावनी इस दृष्टिकोण की नाजुकता के बारे में लागू होती है।
  • किसी कारण से यह कुछ "वैकल्पिक स्थान" में ब्रेकपॉइंट डालता है। एक बार प्रारंभिक डीबगिंग सत्र समाप्त होने के बाद, आपको अपने कोड में नया ब्रेकपॉइंट दिखाई नहीं देता है। लेकिन अगर आप प्रोग्राम को फिर से डीबगर में चलाते हैं, और "सभी ब्रेकपॉइंट अक्षम करें" जैसी चीजें इसे प्रभावित करती हैं। क्या हो रहा है, इसके बारे में जानना अच्छा होगा, अगर कोई इसे साफ़ करने का तरीका ढूंढने जैसा महसूस करता है। शायद .suo फ़ाइल में खोदना?

आशा है कि इससे मदद मिलती है!

+0

वाह !!! (मैं केवल 'वाह !!!' टाइप करना चाहता था लेकिन यह 15 से कम वर्णों की अनुमति नहीं देगा :)) –

+0

स्वीट लॉरी। अगर कोई रास्ता था तो मैं आपको +10 दे सकता था, मैं चाहता था। – DevinB

+0

मुझे वापस आने के लिए अपने फोन में एक अनुस्मारक डालने की आवश्यकता है और कल जब मैं नए वोट प्राप्त करता हूं तो इस जवाब को ऊपर उठाना होगा। :-) – Henric

44

आप बस System.Diagnostics.Debugger.Break() पर कॉल कर सकते हैं।

आप मेनू पर Debug->Exceptions... पर मेनू पर जाकर और Thrown पर जाकर सभी अपवादों को संभालने के लिए विजुअल स्टूडियो को भी बता सकते हैं, जो वर्तमान में केवल "उपयोगकर्ता-अनचाहे" की जांच कर रहा है।

+0

सबसे पहले, (+1) यह कमाल है, मुझे नहीं पता था कि यह अस्तित्व में था। लेकिन, दस्तावेज इंगित करता है कि "यदि कोई डीबगर संलग्न नहीं है, तो उपयोगकर्ताओं से पूछा जाता है कि क्या वे एक डीबगर संलग्न करना चाहते हैं।" इसका अर्थ यह है कि यदि यह डीबगर के बिना चल रहा है तो यह विधि * वर्तमान * निष्पादन प्रवाह को बाधित करेगी। मेरे मामले में, मैं इसे अगली बार ब्रेकपॉइंट सेट करना चाहता हूं। साथ ही, सवाल में कहा गया है कि मैं कॉलिंग फ़ंक्शन में ब्रेकपॉइंट सेट करना चाहता था, क्योंकि (संभवतः) कॉलिंग फ़ंक्शन में महत्वपूर्ण प्रासंगिक जानकारी है जो पारित नहीं हुई थी। – DevinB

+0

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

+7

इसके अलावा, आप ब्रेक कॉल करने से पहले डीबगर की जांच कर सकते हैं। –

2

मुझे नहीं लगता कि आप वास्तव में "एक ब्रेकपाइंट जोड़ें" कर सकते हैं, लेकिन आप डिबगर निष्पादन को निलंबित करने के निर्देश दे ताकि आप जाँच कर सकते हैं क्या गलत हुआ, System.Diagnostics.Debugger.Break()

4
फोन करके कर सकते हैं

यह आपके प्रश्न के लिए वास्तव में उत्तरदायी नहीं है, लेकिन आप Debug.Assert का उपयोग करके सेट की गई स्थितियों के आधार पर डीबगर को तोड़ने का कारण बन सकते हैं। तो, "अगली बार जब मैं एक अपवाद का कारण बनता हूं, तो ब्रेक" चलाता है, तो आप तोड़ने के लिए अपने फ़ंक्शन में दावा जोड़ सकते हैं जब हालात नहीं होते हैं कि उन्हें क्या होना चाहिए। आखिरकार, इस बात की कोई गारंटी नहीं है कि एक समारोह इस बार अपवाद फेंक देगा क्योंकि उसने पिछली बार अपवाद फेंक दिया था। :)

0

इसके अलावा, विजुअल बेसिक में स्टॉप नामक एक कीवर्ड है जो अनिवार्य रूप से ब्रेक पॉइंट के रूप में कार्य करेगा और निष्पादन को तोड़ देगा।

+1

मेरा मानना ​​है कि आपने प्रश्न को गलत समझा होगा। मैं निष्पादन प्रोग्राम पीडीबी फ़ाइल, * नहीं * स्रोत कोड को संशोधित करना चाहता हूं। इस तरह, मैं इसे सामान्य रूप से पहली बार चला सकता हूं, और देख सकता हूं कि यह कैसे संभालता है, और फिर मैं एक डीबगर संलग्न कर सकता हूं, और पिछली बार विफल होने वाले सभी स्थानों पर ब्रेकपॉइंट पहले ही स्थापित हो जाएंगे। आपका स्टॉप समाधान * हमेशा * निष्पादन रोक देगा। – DevinB

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