В рамках обработки некоторых ошибок в нашем продукте мы хотели бы вывести некоторую информацию о трассировке стека. Однако мы видим, что многие пользователи просто сделают снимок экрана диалогового окна сообщения об ошибке вместо того, чтобы отправить нам копию полного отчета, доступного из программы, и поэтому я хотел бы сделать доступной в этом диалоговом окне некоторую минимальную информацию трассировки стека.
Трассировка стека .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
Любые советы, которые вы дадите, будут полезны.





Вы должны иметь возможность получить объект StackTrace вместо строки, сказав
var trace = new System.Diagnostics.StackTrace(exception);
Затем вы можете сами посмотреть на фреймы, не полагаясь на форматирование фреймворка.
См. Также: Ссылка на StackTrace
Ооо, мило, я этого не знала! Я обязательно займусь этим.
В режиме выпуска вы все еще можете точно получить трассировку стека исключения?
Я сериализую исключение в файл. SerializationHelper.Serialize(@"c:\temp\ConfigurationErrorsExceptions.ser", ex); Если я десериализую из файла var exception = SerializationHelper.Deserialize(@"ConfigurationErrorsExceptions.ser");, След будет нет в наличииvar trace = new System.Diagnostics.StackTrace(exception as Exception);, FrameCount будет 0
В качестве альтернативы 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
...
Не могли бы вы пояснить, что вы имеете в виду, говоря о том, что log4net «потенциально опасен»?
Я не знаю наверняка, что имел в виду Oglester, но я знаю, что у stackoverflow.com были некоторые проблемы с взаимоблокировкой, потому что log4net регистрировал исключения в базе данных. У меня лично не было никаких проблем, но я сохраняю простоту и придерживаюсь прокатки текстовых файлов.
Если вы не будете правильно управлять своими ссылками, вы получите утечку памяти. Веб-сайт, над которым я работал некоторое время назад, широко использует log4net (катящиеся файлы). Поскольку log4net ссылается на файл (небезопасно), вы должны быть уверены, что сохранили ссылки log4net в чистоте или до минимума.
Вот код, который я использую для этого без исключения
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));
}
}
Вы могли бы подумать, что это будет где-то встроено в функциональность, поскольку обработчик исключений делает это изначально.
Просто чтобы сделать это 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();
}
(на основе ответа Линдхольма)
Спасибо за это. Обратите внимание, что вы можете использовать sb.AppendLine (...), чтобы избежать жесткого кодирования конкретного символа конца строки.
Или есть еще более короткая версия ..
Console.Write(exception.StackTrace);
Я хотел бы, чтобы кто-то дал ответ на синтаксический анализ, поскольку я работаю с записанными строками из произвольных приложений и действительно надеялся получить некоторые подробности по этому поводу. Учитывая, что у вас есть контроль над источником StackTrace, вы действительно выбрали правильный ответ :)