Вывести информацию трассировки стека из C # - PullRequest
51 голосов
/ 09 сентября 2008

В рамках некоторой обработки ошибок в нашем продукте мы хотели бы получить некоторую информацию о трассировке стека. Однако мы сталкиваемся с тем, что многие пользователи просто делают снимок экрана с диалоговым окном сообщения об ошибке, а не посылают нам копию полного отчета, доступного из программы, и поэтому я хотел бы сделать некоторую минимальную информацию о трассировке стека доступной в этом диалоговом окне.

Трассировка стека .NET на моей машине выглядит следующим образом:

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
at System.IO.StreamReader..ctor(String path)
at LVKWinFormsSandbox.MainForm.button1_Click(Object sender, EventArgs e) in C:\Dev\VS.NET\Gatsoft\LVKWinFormsSandbox\MainForm.cs:line 36

У меня есть вопрос:

Формат выглядит следующим образом:

at <class/method> [in file:line ##]

Тем не менее, в и в ключевых словах, я предполагаю, что они будут локализованы, если они будут запускать, скажем, норвежскую среду выполнения .NET вместо установленной мной английской.

Можно ли как-нибудь выделить эту трассировку стека не зависящим от языка образом, чтобы я мог отобразить только номер файла и номер строки для тех записей, которые имеют это?

Другими словами, я хотел бы получить эту информацию из приведенного выше текста:

C:\Dev\VS.NET\Gatsoft\LVKWinFormsSandbox\MainForm.cs:line 36

Любой совет, который вы можете дать, будет полезен.

Ответы [ 5 ]

71 голосов
/ 09 сентября 2008

Вы должны иметь возможность получить объект StackTrace вместо строки, сказав

var trace = new System.Diagnostics.StackTrace(exception);

Затем вы можете самостоятельно просматривать кадры, не полагаясь на форматирование платформы.

См. Также: Ссылка на StackTrace

28 голосов
/ 06 августа 2009

Вот код, который я использую для этого без исключения

public static void LogStack()
{
  var trace = new System.Diagnostics.StackTrace();
  foreach (var frame in trace.GetFrames())
  {
    var method = frame.GetMethod();
    if (method.Name.Equals("LogStack")) continue;
    Log.Debug(string.Format("{0}::{1}", 
        method.ReflectedType != null ? method.ReflectedType.Name : string.Empty,
        method.Name));
  }
}
18 голосов
/ 22 мая 2011

Просто чтобы сделать это 15-секундным ответом копирования-вставки:

static public string StackTraceToString()
{
    StringBuilder sb = new StringBuilder(256);
    var frames = new System.Diagnostics.StackTrace().GetFrames();
    for (int i = 1; i < frames.Length; i++) /* Ignore current StackTraceToString method...*/
    {
        var currFrame = frames[i];
        var method = currFrame.GetMethod();
        sb.AppendLine(string.Format("{0}:{1}",                    
            method.ReflectedType != null ? method.ReflectedType.Name : string.Empty,
            method.Name));
    }
    return sb.ToString();
}

(на основе ответа Линдхольма)

8 голосов
/ 08 января 2012

Или есть еще более короткая версия ..

Console.Write(exception.StackTrace);
0 голосов
/ 09 сентября 2008

В качестве альтернативы log4net, хотя и потенциально опасный, дал мне лучшие результаты, чем System.Diagnostics. По сути, в log4net у вас есть метод для различных уровней журнала, каждый с параметром Exception. Поэтому, когда вы передадите второе исключение, оно выведет трассировку стека любому настроенному вами приложению.

пример: Logger.Error("Danger!!!", myException );

Вывод, в зависимости от конфигурации, выглядит примерно так:

System.ApplicationException: Something went wrong.
   at Adapter.WriteToFile(OleDbCommand cmd) in C:\Adapter.vb:line 35
   at Adapter.GetDistributionDocument(Int32 id) in C:\Adapter.vb:line 181
   ...
...