Jak wydrukować bieżące śledzenie stosu w .NET bez wyjątku?

348

Mam zwykły kod C #. Nie mam wyjątków . Chcę programowo rejestrować bieżące dane śledzenia stosu w celu debugowania. Przykład:

public void executeMethod() 
{
    logStackTrace();
    method();
}
Ricibald
źródło

Odpowiedzi:

399

Spójrz na System.Diagnosticsprzestrzeń nazw. Wiele gadżetów!

System.Diagnostics.StackTrace t = new System.Diagnostics.StackTrace();

Naprawdę dobrze jest się wkurzyć, aby dowiedzieć się, co się dzieje pod maską.

Polecam przyjrzeć się rozwiązaniom rejestrowania (takim jak NLog, log4net lub wzorce i praktyki Microsoft Enterprise Library), które mogą osiągnąć twoje cele, a następnie niektóre. Powodzenia, kolego!

Spence
źródło
74
Pamiętaj, że piesStackTrace jest wolny - używaj go oszczędnie.
Jonathan Dickinson
213

Alternatywą System.Diagnostics.StackTracejest użycie System.Environment.StackTrace, która zwraca ciąg reprezentacji stosu.

Inną przydatną opcją jest użycie zmiennych$CALLER i $CALLSTACK debugowanie w Visual Studio, ponieważ można to włączyć w czasie wykonywania bez przebudowywania aplikacji.

larsmoa
źródło
6
Environment.StackTracewłaśnie pojawiło się nowe wystąpienie StackTrace.
Daniel
9
@Daniel: Tak, ale System.Environment.StackTracemoże być wygodniejszym sposobem uzyskiwania dostępu do tych informacji.
larsmoa
6
@AndreiRinea: Właściwie wierzę, że możesz uzyskać dostęp do numerów linii za pomocą System.Diagnostics.StackTrace- patrz msdn.microsoft.com/en-us/library/…
larsmoa
5
Czy to nie denerwujące, że Environment.StackTracezawsze zaczyna się od at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace()? To nie jest część aktualnego śladu stosu w momencie, gdy ktoś go szuka.
Rory,
7
@Rory, spójrz na konstruktor StackTrace (int skipFrames, bool fNeedFileInfo), możesz pominąć ramkę początkową. ipen metodę w ILSpy i można zobaczyć, co robi
Walter Vehoeven
39

Można to zrobić na dwa sposoby. System.Diagnostics.StackTrace()Daje ślad stosu dla bieżącego wątku. Jeśli masz odwołanie do Threadinstancji, możesz uzyskać ślad stosu dla tego poprzez przeciążoną wersję StackTrace().

Możesz także sprawdzić pytanie Przepełnienie stosu Jak uzyskać śledzenie stosu nieaktualnego wątku? .

Brian Rasmussen
źródło
16

Można to również zrobić w debugerze programu Visual Studio bez modyfikowania kodu.

  1. Utwórz punkt przerwania, w którym chcesz zobaczyć ślad stosu.
  2. Kliknij punkt przerwania prawym przyciskiem myszy i wybierz „Działania ...” w VS2015. W VS2010 wybierz „Po trafieniu ...”, a następnie włącz „Wydrukuj wiadomość”.
  3. Upewnij się, że wybrano „Kontynuuj wykonywanie”.
  4. Wpisz tekst, który chcesz wydrukować.
  5. Dodaj $ CALLSTACK wszędzie tam, gdzie chcesz zobaczyć ślad stosu.
  6. Uruchom program w debugerze.

Oczywiście nie pomaga to, jeśli uruchamiasz kod na innym komputerze, ale może być całkiem przydatne, aby móc wypluć ślad stosu automatycznie bez wpływu na kod wersji lub nawet bez konieczności ponownego uruchamiania programu.

Hank Schultz
źródło
7
Jeśli chcesz zobaczyć ślad stosu i jesteś już w debuggerze VS w punkcie przerwania, po prostu przejdź do Debuguj-> Windows-> Stos wywołań.
khargoosh
5
Tak, ale jeśli zrobisz to w ten sposób, program nie musi się zatrzymywać, aby zobaczyć ślad stosu.
Hank Schultz
7
Console.WriteLine(
    new System.Diagnostics.StackTrace().ToString()
    );

Dane wyjściowe będą podobne do:

w YourNamespace.Program.executeMethod (ciąg msg)

at YourNamespace.Program.Main (Argumenty String [])

Zastąp Console.WriteLineswoją Logmetodą. W rzeczywistości nie ma potrzeby stosowania .ToString()konsoli Console.WriteLine, ponieważ akceptuje object. Ale może być to potrzebne do metody Log (string msg).

epoksyd
źródło
-2
   private void ExceptionTest()
    {
        try
        {
            int j = 0;
            int i = 5;
            i = 1 / j;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
            var stList = ex.StackTrace.ToString().Split('\\');
            Console.WriteLine("Exception occurred at " + stList[stList.Count() - 1]);
        }
    }

Wydaje się dla mnie pracować

Jeff Jacobs
źródło
3
To tylko generuje oczywisty wyjątek. Dlaczego? Dlaczego nie po prostu jawnie utworzyć wyjątek, zamiast wady, która sama w sobie spowoduje wyjątek? Jaka jest korzyść z dodatkowej logiki połowu wymaganej do uzyskania faktycznego wyjątku? I nawet wtedy nadal ignorujesz opublikowane pytanie, w jaki sposób uzyskać ślad stosu bez żadnego wyjątku (przeczytaj tytuł).
Flater
to ważna odpowiedź, ale okropne rozwiązanie. Nikt nie powinien jej używać ... @Jeff, gdziekolwiek to zrobiłeś, zastąp go kodem zejścia, tak jak inne sugerowane odpowiedzi.
Tomer W