Come stampare l'attuale Stack Trace in .NET senza alcuna eccezione?


350

Ho un codice C # regolare. Non ho eccezioni . Voglio registrare a livello di codice la traccia dello stack corrente a scopo di debug. Esempio:

public void executeMethod() 
{
    logStackTrace();
    method();
}

Risposte:


400

Dai un'occhiata allo System.Diagnosticsspazio dei nomi. Un sacco di chicche lì dentro!

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

È davvero bello dare un'occhiata in giro per imparare cosa succede sotto il cofano.

Ti consiglierei di dare un'occhiata alle soluzioni di registrazione (come NLog, log4net o la libreria Enterprise di modelli e pratiche di Microsoft) che potrebbero raggiungere i tuoi scopi e poi alcuni. Buona fortuna amico!


74
Tieni presente che il caneStackTrace è lento , quindi usalo con parsimonia.
Jonathan Dickinson,

214

Un'alternativa System.Diagnostics.StackTraceè utilizzare System.Environment.StackTrace che restituisce una rappresentazione in formato stringa dello stacktrace.

Un'altra opzione utile è utilizzare le variabili di debug$CALLER e $CALLSTACK in Visual Studio poiché può essere abilitato in fase di esecuzione senza ricostruire l'applicazione.


6
Environment.StackTracesolo una novità è un'istanza di StackTrace.
Daniel,

9
@Daniel: Sì, ma System.Environment.StackTracepotrebbe essere un modo più conveniente di accedere a tali informazioni.
Larsmoa,

6
@AndreiRinea: In realtà, I belive è possibile accedere utilizzando i numeri di riga System.Diagnostics.StackTrace- vedi msdn.microsoft.com/en-us/library/...
larsmoa

5
Non è fastidioso che Environment.StackTraceinizia sempre con at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace()? Non fa parte della traccia dello stack corrente come nel punto in cui qualcuno la sta cercando.
Rory,

7
@Rory, dai un'occhiata al costruttore StackTrace (int skipFrames, bool fNeedFileInfo), puoi saltare il frame iniziale. ipen il metodo in ILSpy e puoi vedere cosa fa
Walter Vehoeven,

39

Ci sono due modi per farlo. Il System.Diagnostics.StackTrace()vi darà una traccia dello stack per il thread corrente. Se si ha un riferimento a Threadun'istanza, è possibile ottenere la traccia dello stack per tale tramite la versione sovraccarica di StackTrace().

Potresti anche voler dare un'occhiata alla domanda Stack Overflow Come ottenere lo stacktrace del thread non corrente? .


16

È inoltre possibile farlo nel debugger di Visual Studio senza modificare il codice.

  1. Creare un punto di interruzione in cui si desidera vedere la traccia dello stack.
  2. Fare clic con il tasto destro del mouse sul punto di interruzione e selezionare "Azioni ..." in VS2015. In VS2010, seleziona "When Hit ...", quindi abilita "Stampa un messaggio".
  3. Assicurati che "Continua esecuzione" sia selezionato.
  4. Digita il testo che desideri stampare.
  5. Aggiungi $ CALLSTACK ovunque tu voglia vedere la traccia dello stack.
  6. Esegui il programma nel debugger.

Naturalmente, questo non aiuta se stai eseguendo il codice su un altro computer, ma può essere abbastanza utile essere in grado di sputare automaticamente una traccia dello stack senza influire sul codice di rilascio o senza nemmeno dover riavviare il programma.


7
Se vuoi vedere una traccia dello stack e sei già nel debugger VS in un punto di interruzione, vai su Debug-> Windows-> Chiama stack.
Khargoosh,

5
Sì, ma se lo fai in questo modo, il programma non deve fermarsi per vedere la traccia dello stack.
Hank Schultz,

7
Console.WriteLine(
    new System.Diagnostics.StackTrace().ToString()
    );

L'output sarà simile a:

at YourNamespace.Program.executeMethod (String msg)

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

Sostituisci Console.WriteLinecon il tuo Logmetodo. In realtà, non è necessario .ToString()per il caso Console.WriteLine come accetta object. Ma potresti averne bisogno per il tuo metodo Log (string msg).


-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]);
        }
    }

Sembra funzionare per me


3
Questo sta solo generando un'eccezione evidente. Perché? Perché non semplicemente istanziare esplicitamente un'eccezione, piuttosto che un difetto che solleverà un'eccezione in sé e per sé? Qual è il vantaggio della logica di cattura aggiuntiva richiesta per ottenere l'eccezione effettiva? E anche allora, stai ancora ignorando l'effettiva domanda postata su come ottenere una traccia dello stack senza alcuna eccezione (leggi il titolo).
Flater,

è una risposta valida, ma una soluzione terribile per Dio. NESSUNO DOVREBBE UTILIZZARLO ... @Jeff ovunque tu l'abbia fatto, sostituiscilo con un codice di discesa come le altre risposte suggerite.
Tomer W,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.