2008-12-11 13 views
57

Szukam sposobu w .NET (2.0, C# w szczególności) dla kodu źródłowego, aby wywołać przerwę debugowania, jak gdyby punkt przerwania był ustawiony w tym punkcie, bez konieczności pamiętania, aby ustawić konkretny punkt przerwania tam w debugerze i bez ingerencji w środowisko wykonawcze produkcji.Czy kod źródłowy .NET może zakodować twardy punkt debugowania?

Nasz kod musi przełknąć wyjątki w produkcji, aby nie zakłócać aplikacji klienckiej, która łączy się z nami, ale próbuję skonfigurować tak, aby takie błędy pojawiały się, aby zostać przeanalizowane, jeśli tak się stanie uruchomiony w debugerze, w przeciwnym razie zostanie bezpiecznie zignorowany.

Moja próba użycia Debug.Assert(false) była mniej niż idealna i zakładam, że Debug.Fail() zachowałoby się w ten sam sposób. Teoretycznie nie powinno to mieć żadnego wpływu na produkcję i kończy się pomyślnie podczas debugowania, ale według projektu (o ile mogę to stwierdzić) nie można kontynuować wykonywania, jeśli chcesz zignorować ten błąd, tak jak przy rzeczywistym punkcie przerwania i tak jak w przypadku produkcji, w której połkniemy błąd. Najwyraźniej również przerywa ocenę stanu zmiennej, ponieważ debugger faktycznie zatrzymuje się w macierzystym kodzie systemowym, a nie w naszym, więc pomoc w debugowaniu jest ograniczona. (Może brakuje mi sposobu na powrót do rzeczy, aby spojrzeć na zmienne i tak dalej, gdzie to się stało?)

Miałem nadzieję na coś takiego jak Debug.Break(), ale wydaje się, że nie istnieje (chyba że w późniejszej wersji .NET?) i żadne inne metody nie wydają się mieć zastosowania.

Aktualizacja: Chociaż odpowiedź ctacke jest najlepiej pasuje do tego, co szukałem, mam odkąd odkrył również trick z Debug.Assert() - gdy uruchomiony w debugera - Pauza debuggera, przejdź do kod wywołania Debug.Asering (podświetlony na zielono, ponieważ jest w kodzie źródłowym) i naciśnij Step-Out (shift-F11), a następnie naciśnij Ignore w oknie dialogowym potwierdzenia. Spowoduje to wstrzymanie debuggera po powrocie assert (i będzie w stanie kontynuować wykonywanie, jakby nie było, ponieważ zostało zignorowane). Mogą istnieć inne sposoby robienia tego samego (czy uderzenie Spróbuj zrobić to bardziej bezpośrednio?), Ale w ten sposób było intuicyjne.

Odpowiedz

109

prawdopodobnie jesteś po coś takiego:

if(System.Diagnostics.Debugger.IsAttached) 
    System.Diagnostics.Debugger.Break(); 

Oczywiście który nadal będzie kompilowany w wersji Release. Jeśli chcesz, aby zachowywać się bardziej jak obiektu Debug gdzie kod po prostu nie istnieje w kompilacji Release, a następnie można zrobić coś takiego:

[Conditional("DEBUG")] 
void DebugBreak() 
{ 
    if(System.Diagnostics.Debugger.IsAttached) 
    System.Diagnostics.Debugger.Break(); 
} 

następnie dodać do niego zadzwonić w kodzie.

+2

możesz również użyć #if DEBUG ... #endif zamiast –

+10

Oczywiście, ale jest o wiele brzydszy niż warunkowy, ponieważ musisz zawijać każde wywołanie metody również za pomocą dyrektywy prekompilatora. – ctacke

+0

Aby wyjaśnić, z MSDN: 'Gdy wywoływana jest metoda oznaczona jako warunkowa, obecność lub nieobecność określonego symbolu przetwarzania wstępnego określa, czy wywołanie jest uwzględniane czy pominięte. Jeśli symbol jest zdefiniowany, połączenie jest włączone; w przeciwnym razie wywołanie zostanie pominięte. "oraz" Metoda warunkowa musi być metodą w klasie lub deklaracji struct i musi mieć typ powrotu typu void. " – Kiruse

11

System.Diagnostics.Debugger.Break?

+0

(Oryginalnie odpowiedziano w grudniu 2008 r. Jako kolejna odpowiedź, zanim wiedziałem, że mogę skomentować odpowiedzi na moje własne pytanie): Ahhh, dzięki, Shahkalpesh. System.Diagnostics.Debugger.Break() to dobry początek! Tego właśnie mi brakowało, pod Debugger zamiast Debug. Wygląda na to, że to przerwie i poprosi o dołączenie debuggera, którego mógłbym uniknąć. Ale wygląda na to, że jeśli (Debugger.IsAttached) Debugger.Break(); ... robi to, czego szukam, jak sugerował ctacke. Debugger.Launch() może działać dla nieco innych sesji, w których chcesz mieć debugger, jeśli już go nie ma. –

8

Pobiegłem do sytuacji, w której ten jeden raz nie działa

System.Diagnostics.Debugger.Break(); 

ale ten zrobił

System.Diagnostics.Debugger.Launch(); 
+0

Jeśli Debugger nie jest dołączony, to musisz najpierw dołączyć go za pomocą Debugger.Launch(), możesz użyć Debugger.Break(). Jest to konieczne, jeśli chcesz debugować rozwiązanie, w którym jeden proces rozpoczyna inny proces i chcesz debugować oba. –

4

Co powiesz na skonfigurowanie programu Visual Studio tak, aby pojawiał się z debugerem, nawet jeśli go połkniesz?

Wykonaj:

  • idź do Debug-> Wyjątki ...
  • Znajdź odpowiedni wyjątek lub dodać go, jeśli jest to twój własny
  • sprawdzić „rzucony” pole za wyjątkiem

To zatrzyma Visual Studio w miejscu, które jest wyjątek, nie tylko jeśli to nie jest obsługiwane.

Możesz zobaczyć więcej informacji here.

+0

To jest sztuczka warta wzmianki. Jest to szczególnie pomocne w identyfikacji miejsca, w którym problem występuje po raz pierwszy (i nadal uzyskuje się państwo członkowskie, a nie tylko ślad stosu wyjątków?). Ale w tym przypadku chciałbym, aby źródło powiadomiło nas o wyjątkach, których nie oczekujemy i nie można ich skonfigurować. –

3

Miłą sztuczką, którą znalazłem jest umieszczenie Debugger.Break() w ctor swojego wyjątku.

+0

Fajna sztuczka. Oczywiście nie jest to dobre dla wyjątków systemowych, ale możemy spróbować tego z naszymi własnymi typami wyjątków, zależnie od statycznego elementu lub dwóch, abyśmy mogli go włączać i wyłączać, a także sprawdzać Debugger.IsAttached; jedno ustawienie może Break()/Launch() nawet bez IsAttached, inne tylko jeśli jest. –

1

W Visual Studio 2010, trafiając Retry w oknie Debug.Assert zabierze cię do nieudanej debugowania twierdzenia, jak gdybyś miał przerwania.

+0

Hmmm, dzięki. Muszę spróbować tego następnym razem, gdy uderzę w asercie podczas debuggera. Nigdy nie miałem pojęcia, co miało oznaczać "Retry". Być może jest to zatrzymanie z poprzedniego użycia tego okna dialogowego. –

+1

To na pewno słabo sformułowane okno dialogowe. –

4

Jeśli chcesz mieć tylko jedną linię kodu zamiast 4, owinąć

#if DEBUG 
     if (Debugger.IsAttached) 
      Debugger.Break(); 
#endif 

do

public static class DebugHelper 
{ 
    [DebuggerHidden] 
    [Conditional("DEBUG")] 
    public static void Stop() 
    { 
     if (Debugger.IsAttached) 
      Debugger.Break(); 
    } 
} 

i używać

DebugHelper.Stop(); 

DebuggerHiddenAttribute jest dodawany, aby zapobiec debugger od zatrzymania się na wewnętrznym kodzie metody Stop i fr om wkroczenie do metody za pomocą F11.

+0

+1 dla sugestii i wyjaśnienia '[DebuggerHidden]'; co sprawiłoby, że metoda skompilowana warunkowo byłaaby jeszcze bardziej przydatna. Czy wiesz, jak długo ten atrybut był obsługiwany? Czy jest to coś zupełnie nowego, czy nawet wraca do wersji .NET 2.0 i VS 2010? –

+0

Przypuszczam, że pochodzi z wersji 1.1 https://msdn.microsoft.com/en-us/library/3a4d38ze(v=vs.71).aspx – Sergey

+0

Lub nawet od wersji 1.0 - wcześniejszej niż Debugger.Break() . https://msdn.microsoft.com/library/system.diagnostics.debugger.break(v=vs.110).aspx Warto zauważyć, że zachowanie metody Break() zostało zmienione z wersji 4.0 dla przypadków, gdy debugger nie jest dołączony. – Sergey