Печать информации трассировки стека из С#

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

Трассировка стека .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 ##]

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

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

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

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

Ответ 3

Просто чтобы сделать это 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();
}

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

Ответ 4

Или существует даже более короткая версия.

Console.Write(exception.StackTrace);

Ответ 5

Как альтернатива, 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
   ...