Como imprimir o rastreamento de pilha atual no .NET sem nenhuma exceção?

349

Eu tenho um código C # regular. Eu não tenho exceções . Desejo registrar programaticamente o rastreamento de pilha atual para fins de depuração. Exemplo:

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

Respostas:

399

Dê uma olhada no System.Diagnosticsespaço para nome. Muitas guloseimas lá!

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

É muito bom dar uma olhada para saber o que está acontecendo sob o capô.

Eu recomendo que você analise as soluções de log (como NLog, log4net ou os padrões e práticas da Microsoft Enterprise Library) que podem atingir seus objetivos e mais alguns. Boa sorte, meu caro!

Spence
fonte
74
Lembre-se de que o cãoStackTrace é lento - use-o com moderação.
Jonathan Dickinson
214

Uma alternativa System.Diagnostics.StackTraceé usar System.Environment.StackTrace, que retorna uma representação de seqüência de caracteres do stacktrace.

Outra opção útil é usar as variáveis ​​de depuração$CALLER e $CALLSTACK no Visual Studio, pois isso pode ser ativado em tempo de execução sem reconstruir o aplicativo.

Larsmoa
fonte
6
Environment.StackTraceapenas novo é uma instância de StackTrace.
Daniel
9
@ Daniel: Sim, mas System.Environment.StackTracepode ser uma maneira mais conveniente de acessar essas informações.
Larsmoa
6
@AndreiRinea: Na verdade, eu acredito que você pode acessar os números de linha usando System.Diagnostics.StackTrace- ver msdn.microsoft.com/en-us/library/...
larsmoa
5
Não é chato que Environment.StackTracesempre começa at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace()? Isso não faz parte do rastreamento de pilha atual, pois alguém está procurando por ele.
Rory
7
@Rory, dê uma olhada no construtor StackTrace (int skipFrames, bool fNeedFileInfo), você pode pular o quadro inicial. IPEN o método em ILSpy e você pode ver o que ele faz
Walter Vehoeven
39

Existem duas maneiras de fazer isso. O System.Diagnostics.StackTrace()vai lhe dar um rastreamento de pilha para o segmento atual. Se você tiver uma referência a uma Threadinstância, poderá obter o rastreamento de pilha para isso através da versão sobrecarregada de StackTrace().

Você também pode conferir a questão Stack Overflow. Como obter o stacktrace do thread não atual? .

Brian Rasmussen
fonte
16

Você também pode fazer isso no depurador do Visual Studio sem modificar o código.

  1. Crie um ponto de interrupção onde deseja ver o rastreamento da pilha.
  2. Clique com o botão direito do mouse no ponto de interrupção e selecione "Ações ..." no VS2015. No VS2010, selecione "When Hit ..." e ative "Print a message".
  3. Verifique se a opção "Continuar execução" está selecionada.
  4. Digite algum texto que você deseja imprimir.
  5. Adicione $ CALLSTACK onde quiser ver o rastreamento da pilha.
  6. Execute o programa no depurador.

Obviamente, isso não ajuda se você estiver executando o código em uma máquina diferente, mas pode ser bastante útil poder citar um rastreamento de pilha automaticamente sem afetar o código de liberação ou sem precisar reiniciar o programa.

Hank Schultz
fonte
7
Se você deseja ver um rastreamento de pilha e já está no depurador do VS em um ponto de interrupção, basta ir em Debug-> Windows-> Call Stack.
Khargoosh
5
Sim, mas se você fizer dessa maneira, o programa não precisará parar para que você veja o rastreamento da pilha.
Hank Schultz
7
Console.WriteLine(
    new System.Diagnostics.StackTrace().ToString()
    );

A saída será semelhante a:

em YourNamespace.Program.executeMethod (String msg)

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

Substitua Console.WriteLinepelo seu Logmétodo. Na verdade, não há necessidade .ToString()do caso Console.WriteLine, pois ele aceita object. Mas você pode precisar disso para o seu método Log (string msg).

epóxi
fonte
-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]);
        }
    }

Parece funcionar para mim

Jeff Jacobs
fonte
3
Isso está apenas gerando uma exceção óbvia. Por quê? Por que não simplesmente instanciar explicitamente uma exceção, em vez de uma falha que criará uma exceção por si só? Qual é o benefício da lógica de captura adicional necessária para obter a exceção real? E mesmo assim, você ainda está ignorando a pergunta real postada sobre como obter um rastreamento de pilha sem nenhuma exceção (leia o título).
Flater
é uma resposta válida, mas uma solução horrível. Ninguém deve usá-lo ... @ Jeff, onde quer que você tenha feito isso, substitua-o por um código de descida como as outras respostas sugeridas.
Tomer W