2008-10-16 2 views
244

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

Итак, как мы можем регистрировать сообщения об ошибках на английском языке без изменения культуры пользователей?

+6

Почему вы не можете выключтель так: CultureInfo oldCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture ("en"); // throw new Exception here => Культура на английском языке Thread.CurrentThread.CurrentCulture = oldCulture; – CheGueVerra 2008-10-16 16:23:23

+47

Я не знаю разработчика, который доволен сообщениями об исключениях, отличных от английского: S .. – 2013-04-30 08:10:14

+1

@ Zéiksz Посмотрите за пределы англоязычных стран, и вы найдете много из них: D. Проблема не в тексте, не являющемся английским, проблема - это язык, который вы не можете понять. Сообщения на вашем родном языке (при условии правильного перевода) совершенно прекрасны. – Alejandro 2016-11-22 12:48:33

ответ

58

Эта проблема может быть частично решена. Код исключения Framework загружает сообщения об ошибках из своих ресурсов на основе текущей локали потока. В случае некоторых исключений это происходит во время доступа к свойству Message.

Для этих исключений вы можете получить полную версию сообщения на английском языке, кратко переведя языковой стандарт потока в en-US во время его регистрации (предварительно сохраните исходный язык пользователя и сразу же восстановите его).

Выполнение этого в отдельной теме еще лучше: это гарантирует, что побочных эффектов не будет. Например:

try 
{ 
    System.IO.StreamReader sr=new System.IO.StreamReader(@"c:\does-not-exist"); 
} 
catch(Exception ex) 
{ 
    Console.WriteLine(ex.ToString()); //Will display localized message 
    ExceptionLogger el = new ExceptionLogger(ex); 
    System.Threading.Thread t = new System.Threading.Thread(el.DoLog); 
    t.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); 
    t.Start(); 
} 

Где класс ExceptionLogger выглядит примерно так:

class ExceptionLogger 
{ 
    Exception _ex; 

    public ExceptionLogger(Exception ex) 
    { 
    _ex = ex; 
    } 

    public void DoLog() 
    { 
    Console.WriteLine(_ex.ToString()); //Will display en-US message 
    } 
} 

Однако, как Joe правильно указывает в комментарии к более ранней ревизии этого ответа, некоторые сообщения уже (частично) загружаемых из языковых ресурсов на момент исключения.

Это относится к тому, что часть параметра не может быть нулевой частью сообщения, генерируемого, например, при генерации исключения ArgumentNullException («foo»). В этих случаях сообщение будет по-прежнему отображаться (частично) локализованным даже при использовании вышеуказанного кода.

За исключением использования непрактичных взломов, таких как запуск всего вашего кода, отличного от UI, в потоке с локалью en-US для начала, похоже, вы ничего не можете с этим сделать: .NET Framework код исключения не имеет возможности для переопределения языкового стандарта сообщения об ошибке.

+8

Ваш пример работает для FileNotFoundException, потому что ресурс сообщения извлекается при доступе к свойству Message, а не при вызове исключения. Но это не относится ко всем исключениям (например, try throw new ArgumentNullException ("paramName")) – Joe 2008-10-16 20:03:32

+3

Я смущен. Я пробовал следовать вашему ответу и проверить его. Я хотел, чтобы мое исключение было на французском языке, поэтому я сделал t.CurrentUICulture = новый System.Globalization.CultureInfo («fr-FR»); `и` t.CurrentCulture = новая система. Globalization.CultureInfo ("fr-FR"); `еще, результирующее исключение было на английском языке ... – VitalyB 2011-10-23 22:10:23

+0

Также не работает для исключения недопустимого имени узла из сокета. – hakan 2013-07-12 08:24:17

4

Я предположил бы, что один из этих подходов:

1) Исключение составляют только когда-либо прочитана вами, то есть они не являются особенностью клиента, так что вы можете использовать проводные удобства локализованные строки, которые не изменяются при работать в турецком режиме.

2) Введите код ошибки, например. 0X00000001 с каждой ошибкой, чтобы вы могли легко просмотреть его в английской таблице.

+3

Это не поможет, потому что они являются исключениями, создаваемыми внутренними компонентами .net framework_. Вся эта проблема не применяется к исключениям, которые вы бросаете сами; очевидно, программист выбирает, что сообщение должно включать в себя _those_. – Nyerguds 2016-06-21 14:27:13

1
CultureInfo oldCI = Thread.CurrentThread.CurrentCulture; 

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture ("en-US"); 
Thread.CurrentThread.CurrentUICulture=new CultureInfo("en-US"); 
try 
{ 
    System.IO.StreamReader sr=new System.IO.StreamReader(@"c:\does-not-exist"); 
} 
catch(Exception ex) 
{ 
    Console.WriteLine(ex.ToString()) 
} 
Thread.CurrentThread.CurrentCulture = oldCI; 
Thread.CurrentThread.CurrentUICulture = oldCI; 

Без РАБОТНИКОВ.

Tks :)

0

Вы должны войти в стек вызовов вместо сообщения об ошибке просто (IIRC, просто exception.ToString() должен сделать это для вас). Оттуда вы можете точно определить, откуда возникло исключение, и обычно вывести, какое это исключение.

5

Windows, необходимо иметь язык интерфейса, который вы хотите использовать установлен. Это не так, у него нет никакого способа узнать, что такое переведенное сообщение.

В смежных США Windows 7 Ultimate, с установленным PT-PT, следующий код:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("pt-PT"); 
string msg1 = new DirectoryNotFoundException().Message; 

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); 
string msg2 = new FileNotFoundException().Message; 

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR"); 
string msg3 = new FileNotFoundException().Message; 

Производит сообщения в PT-PT, EN-US и EN-US. Так как файлы французской культуры не установлены, по умолчанию используется язык по умолчанию (установлен?).

3

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

В регистраторе исключений вы можете войти ex.GetType.ToString, который будет сохранять имя класса исключения. Я ожидал бы, что название класса должно быть не зависящим от языка и поэтому всегда будет представлено на английском языке (например, «System.FileNotFoundException»), хотя в настоящее время у меня нет доступа к системе иностранного языка для проверки идея.

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

2

Установка Thread.CurrentThread.CurrentUICulture будет использоваться для локализации исключений. Если вам нужны два вида исключений (один для пользователя, один для вас), вы можете использовать следующую функцию для перевода сообщения исключения. Он ищет в ресурсах .NET-библиотек для текста orignal для получения ключа ресурса, а затем возвращает переведенное значение. Но одной слабости я еще не нашел хорошего решения: Сообщения, содержащие {0} в ресурсах, не будут найдены. Если у кого-то будет хорошее решение, я был бы благодарен.

public static string TranslateExceptionMessage(Exception E, CultureInfo targetCulture) 
{ 
    try 
    { 
     Assembly a = E.GetType().Assembly; 
     ResourceManager rm = new ResourceManager(a.GetName().Name, a); 
     ResourceSet rsOriginal = rm.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true); 
     ResourceSet rsTranslated = rm.GetResourceSet(targetCulture, true, true); 
     foreach (DictionaryEntry item in rsOriginal) 
      if (item.Value.ToString() == E.Message.ToString()) 
       return rsTranslated.GetString(item.Key.ToString(), false); // success 

    } 
    catch { } 
    return E.Message; // failed (error or cause it's not intelligent enough to locale '{0}'-patterns 
} 
32

спорная точка может быть, но вместо установки культуры en-US, вы можете установить его в Invariant. В культуре Invariant сообщения об ошибках находятся на английском языке.

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; 
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; 

Имеет то преимущество, что не выглядит предвзятым, особенно для неамериканских англоговорящих мест. (a.k.a. избегает комментариев со стороны коллег)

0

Переопределить сообщение об исключении в блоке catch с использованием метода расширения, проверить, что сообщение сброшено из кода или нет, как указано ниже.

public static string GetEnglishMessageAndStackTrace(this Exception ex) 
    { 
     CultureInfo currentCulture = Thread.CurrentThread.CurrentUICulture; 
     try 
     { 

      dynamic exceptionInstanceLocal = System.Activator.CreateInstance(ex.GetType()); 
      string str; 
      Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US"); 

      if (ex.Message == exceptionInstanceLocal.Message) 
      { 
       dynamic exceptionInstanceENG = System.Activator.CreateInstance(ex.GetType()); 

       str = exceptionInstanceENG.ToString() + ex.StackTrace; 

      } 
      else 
      { 
       str = ex.ToString(); 
      } 
      Thread.CurrentThread.CurrentUICulture = currentCulture; 

      return str; 

     } 
     catch (Exception) 
     { 
      Thread.CurrentThread.CurrentUICulture = currentCulture; 

      return ex.ToString(); 
     } 
3

Каркас .NET состоит из двух частей:.

  1. Каркас .NET сама
  2. язык рамки .NET пакеты

Все тексты (сообщения ех исключений, ярлыки кнопок на MessageBox и т. д.) находятся на английском языке в самой платформе .NET. Языковые пакеты имеют локализованные тексты.

В зависимости от вашей конкретной ситуации решением было бы удалить языковые пакеты (т. Е. Сообщить клиенту об этом). В этом случае тексты исключений будут на английском языке. Обратите внимание, однако, что все другие тексты, поставляемые в рамке, также будут на английском языке (например, ярлыки кнопок на MessageBox, сочетания клавиш для ApplicationCommands).

5

Это решение, которое не требует какого-либо кодирования и работает даже для текстов исключений, которые загружаются слишком рано, чтобы мы могли изменять код (например, в mscorlib).

Это может быть не всегда применимо в каждом случае (это зависит от вашей установки, поскольку вам нужно создать файл .config в стороне от основного .exe-файла), но это работает для меня. Таким образом, просто создать в разработчике в app.config, (или [myapp].exe.config или web.config в производстве), который содержит следующие строки, например:

<configuration> 
    ... 
    <runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
     <assemblyIdentity name="mscorlib.resources" publicKeyToken="b77a5c561934e089" culture="fr" /> 
     <bindingRedirect oldVersion="1.0.0.0-999.0.0.0" newVersion="999.0.0.0"/> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="System.Xml.resources" publicKeyToken="b77a5c561934e089" culture="fr" /> 
     <bindingRedirect oldVersion="1.0.0.0-999.0.0.0" newVersion="999.0.0.0"/> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime> 
    ... 
</configuration> 

Что это делает сказать рамки для перенаправления сборочные привязок для ресурсов mscorlib и системы. Ресурсы Xml для версий от 1 до 999 на французском языке (культура установлена ​​в «fr») на сборку, которая ... не существует (произвольная версия 999).

Поэтому, когда CLR будет искать французские ресурсы для этих двух сборок (mscorlib и System.xml), они не найдут их и не отступят от английского изящно. В зависимости от вашего контекста и тестирования вы можете добавить другие сборки в эти переадресации (сборки, содержащие локализованные ресурсы).

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

-1

Для ведения журналов некоторым приложениям может потребоваться получить английское сообщение об исключении (помимо отображения его в UICulture обычного клиента).

Для этой цели, следующий код

  1. изменяет текущий UICulture
  2. воссоздает брошенный объект исключения с помощью "GetType()" & "Activator.CreateInstance (т)"
  3. отображает новые Сообщение об исключении объекта в новом UICuture
  4. , а затем, наконец, изменит текущий UICulture на предыдущий UICulture.

    try 
        { 
         int[] a = { 3, 6 }; 
         Console.WriteLine(a[3]); //Throws index out of bounds exception 
    
         System.IO.StreamReader sr = new System.IO.StreamReader(@"c:\does-not-exist"); // throws file not found exception 
         throw new System.IO.IOException(); 
    
        } 
        catch (Exception ex) 
        { 
    
         Console.WriteLine(ex.Message); 
         Type t = ex.GetType(); 
    
         CultureInfo CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture; 
    
         System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); 
    
         object o = Activator.CreateInstance(t); 
    
         System.Threading.Thread.CurrentThread.CurrentUICulture = CurrentUICulture; // Changing the UICulture back to earlier culture 
    
    
         Console.WriteLine(((Exception)o).Message.ToString()); 
         Console.ReadLine(); 
    
        } 
    
0

У меня была такая же ситуация, и все ответы, которые я нашел здесь и в других местах не помогло или не были удовлетворительными:
Force exceptions language in English
C# - Getting Exception messages in English when the application is in another language?
How to change Visual Studio exception message language to English while debugging
How to handle translation of exception message?
How to completely avoid localized .NET exception messages

Thread.CurrentUICulture изменяет язык исключений .net, но не для Win32Exception, который использует ресурсы Windows на языке самого пользовательского интерфейса Windows. Поэтому я никогда не удался напечатать сообщения из Win32Exception на английском языке, а не немецкий, даже не используя FormatMessage(), как описано в
How to get Win32Exception in English?

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

статических функций этого класса может быть выполнен на установках для Windows с различными языками: CreateMessages() создает тексты культуры конкретной
SaveMessagesToXML() сохраняют их как много файлов XML в качестве языка создан или загружен
LoadMessagesFromXML() загружают все XML файлы со специфическими для языка сообщениями

При создании файлов XML в разных установках Windows на разных языках у вас скоро появятся все необходимые языки.
Возможно, вы можете создавать тексты для разных языков в 1 Windows, если у вас установлено несколько языковых пакетов MUI, но я еще не тестировал их.

Протестировано VS2008, готово к использованию. Комментарии и предложения приветствуются!

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Globalization; 
using System.Reflection; 
using System.Threading; 
using System.Xml; 

public struct CException 
{ 
    //---------------------------------------------------------------------------- 
    public CException(Exception i_oException) 
    { 
    m_oException = i_oException; 
    m_oCultureInfo = null; 
    m_sMessage = null; 
    } 

    //---------------------------------------------------------------------------- 
    public CException(Exception i_oException, string i_sCulture) 
    { 
    m_oException = i_oException; 
    try 
    { m_oCultureInfo = new CultureInfo(i_sCulture); } 
    catch 
    { m_oCultureInfo = CultureInfo.InvariantCulture; } 
    m_sMessage = null; 
    } 

    //---------------------------------------------------------------------------- 
    public CException(Exception i_oException, CultureInfo i_oCultureInfo) 
    { 
    m_oException = i_oException; 
    m_oCultureInfo = i_oCultureInfo == null ? CultureInfo.InvariantCulture : i_oCultureInfo; 
    m_sMessage = null; 
    } 

    //---------------------------------------------------------------------------- 
    // GetMessage 
    //---------------------------------------------------------------------------- 
    public string GetMessage() { return GetMessage(m_oException, m_oCultureInfo); } 

    public string GetMessage(String i_sCulture) { return GetMessage(m_oException, i_sCulture); } 

    public string GetMessage(CultureInfo i_oCultureInfo) { return GetMessage(m_oException, i_oCultureInfo); } 

    public static string GetMessage(Exception i_oException) { return GetMessage(i_oException, CultureInfo.InvariantCulture); } 

    public static string GetMessage(Exception i_oException, string i_sCulture) 
    { 
    CultureInfo oCultureInfo = null; 
    try 
    { oCultureInfo = new CultureInfo(i_sCulture); } 
    catch 
    { oCultureInfo = CultureInfo.InvariantCulture; } 
    return GetMessage(i_oException, oCultureInfo); 
    } 

    public static string GetMessage(Exception i_oException, CultureInfo i_oCultureInfo) 
    { 
    if (i_oException == null) return null; 
    if (i_oCultureInfo == null) i_oCultureInfo = CultureInfo.InvariantCulture; 

    if (ms_dictCultureExceptionMessages == null) return null; 
    if (!ms_dictCultureExceptionMessages.ContainsKey(i_oCultureInfo)) 
     return CreateMessage(i_oException, i_oCultureInfo); 

    Dictionary<string, string> dictExceptionMessage = ms_dictCultureExceptionMessages[i_oCultureInfo]; 
    string sExceptionName = i_oException.GetType().FullName; 
    sExceptionName = MakeXMLCompliant(sExceptionName); 
    Win32Exception oWin32Exception = (Win32Exception)i_oException; 
    if (oWin32Exception != null) 
     sExceptionName += "_" + oWin32Exception.NativeErrorCode; 
    if (dictExceptionMessage.ContainsKey(sExceptionName)) 
     return dictExceptionMessage[sExceptionName]; 
    else 
     return CreateMessage(i_oException, i_oCultureInfo); 
    } 

    //---------------------------------------------------------------------------- 
    // CreateMessages 
    //---------------------------------------------------------------------------- 
    public static void CreateMessages(CultureInfo i_oCultureInfo) 
    { 
    Thread oTH = new Thread(new ThreadStart(CreateMessagesInThread)); 
    if (i_oCultureInfo != null) 
    { 
     oTH.CurrentCulture = i_oCultureInfo; 
     oTH.CurrentUICulture = i_oCultureInfo; 
    } 
    oTH.Start(); 
    while (oTH.IsAlive) 
    { Thread.Sleep(10); } 
    } 

    //---------------------------------------------------------------------------- 
    // LoadMessagesFromXML 
    //---------------------------------------------------------------------------- 
    public static void LoadMessagesFromXML(string i_sPath, string i_sBaseFilename) 
    { 
    if (i_sBaseFilename == null) i_sBaseFilename = msc_sBaseFilename; 

    string[] asFiles = null; 
    try 
    { 
     asFiles = System.IO.Directory.GetFiles(i_sPath, i_sBaseFilename + "_*.xml"); 
    } 
    catch { return; } 

    ms_dictCultureExceptionMessages.Clear(); 
    for (int ixFile = 0; ixFile < asFiles.Length; ixFile++) 
    { 
     string sXmlPathFilename = asFiles[ixFile]; 

     XmlDocument xmldoc = new XmlDocument(); 
     try 
     { 
     xmldoc.Load(sXmlPathFilename); 
     XmlNode xmlnodeRoot = xmldoc.SelectSingleNode("/" + msc_sXmlGroup_Root); 

     string sCulture = xmlnodeRoot.SelectSingleNode(msc_sXmlGroup_Info + "/" + msc_sXmlData_Culture).Value; 
     CultureInfo oCultureInfo = new CultureInfo(sCulture); 

     XmlNode xmlnodeMessages = xmlnodeRoot.SelectSingleNode(msc_sXmlGroup_Messages); 
     XmlNodeList xmlnodelistMessage = xmlnodeMessages.ChildNodes; 
     Dictionary<string, string> dictExceptionMessage = new Dictionary<string, string>(xmlnodelistMessage.Count + 10); 
     for (int ixNode = 0; ixNode < xmlnodelistMessage.Count; ixNode++) 
      dictExceptionMessage.Add(xmlnodelistMessage[ixNode].Name, xmlnodelistMessage[ixNode].InnerText); 
     ms_dictCultureExceptionMessages.Add(oCultureInfo, dictExceptionMessage); 
     } 
     catch 
     { return; } 
    } 
    } 

    //---------------------------------------------------------------------------- 
    // SaveMessagesToXML 
    //---------------------------------------------------------------------------- 
    public static void SaveMessagesToXML(string i_sPath, string i_sBaseFilename) 
    { 
    if (i_sBaseFilename == null) i_sBaseFilename = msc_sBaseFilename; 

    foreach (KeyValuePair<CultureInfo, Dictionary<string, string>> kvpCultureExceptionMessages in ms_dictCultureExceptionMessages) 
    { 
     string sXmlPathFilename = i_sPath + i_sBaseFilename + "_" + kvpCultureExceptionMessages.Key.TwoLetterISOLanguageName + ".xml"; 
     Dictionary<string, string> dictExceptionMessage = kvpCultureExceptionMessages.Value; 

     XmlDocument xmldoc = new XmlDocument(); 
     XmlWriter xmlwriter = null; 
     XmlWriterSettings writerSettings = new XmlWriterSettings(); 
     writerSettings.Indent = true; 

     try 
     { 
     XmlNode xmlnodeRoot = xmldoc.CreateElement(msc_sXmlGroup_Root); 
     xmldoc.AppendChild(xmlnodeRoot); 
     XmlNode xmlnodeInfo = xmldoc.CreateElement(msc_sXmlGroup_Info); 
     XmlNode xmlnodeMessages = xmldoc.CreateElement(msc_sXmlGroup_Messages); 
     xmlnodeRoot.AppendChild(xmlnodeInfo); 
     xmlnodeRoot.AppendChild(xmlnodeMessages); 

     XmlNode xmlnodeCulture = xmldoc.CreateElement(msc_sXmlData_Culture); 
     xmlnodeCulture.InnerText = kvpCultureExceptionMessages.Key.Name; 
     xmlnodeInfo.AppendChild(xmlnodeCulture); 

     foreach (KeyValuePair<string, string> kvpExceptionMessage in dictExceptionMessage) 
     { 
      XmlNode xmlnodeMsg = xmldoc.CreateElement(kvpExceptionMessage.Key); 
      xmlnodeMsg.InnerText = kvpExceptionMessage.Value; 
      xmlnodeMessages.AppendChild(xmlnodeMsg); 
     } 

     xmlwriter = XmlWriter.Create(sXmlPathFilename, writerSettings); 
     xmldoc.WriteTo(xmlwriter); 
     } 
     catch (Exception e) 
     { return; } 
     finally 
     { if (xmlwriter != null) xmlwriter.Close(); } 
    } 
    } 

    //---------------------------------------------------------------------------- 
    // CreateMessagesInThread 
    //---------------------------------------------------------------------------- 
    private static void CreateMessagesInThread() 
    { 
    Thread.CurrentThread.Name = "CException.CreateMessagesInThread"; 

    Dictionary<string, string> dictExceptionMessage = new Dictionary<string, string>(0x1000); 

    GetExceptionMessages(dictExceptionMessage); 
    GetExceptionMessagesWin32(dictExceptionMessage); 

    ms_dictCultureExceptionMessages.Add(Thread.CurrentThread.CurrentUICulture, dictExceptionMessage); 
    } 

    //---------------------------------------------------------------------------- 
    // GetExceptionTypes 
    //---------------------------------------------------------------------------- 
    private static List<Type> GetExceptionTypes() 
    { 
    Assembly[] aoAssembly = AppDomain.CurrentDomain.GetAssemblies(); 

    List<Type> listoExceptionType = new List<Type>(); 

    Type oExceptionType = typeof(Exception); 
    for (int ixAssm = 0; ixAssm < aoAssembly.Length; ixAssm++) 
    { 
     if (!aoAssembly[ixAssm].GlobalAssemblyCache) continue; 
     Type[] aoType = aoAssembly[ixAssm].GetTypes(); 
     for (int ixType = 0; ixType < aoType.Length; ixType++) 
     { 
     if (aoType[ixType].IsSubclassOf(oExceptionType)) 
      listoExceptionType.Add(aoType[ixType]); 
     } 
    } 

    return listoExceptionType; 
    } 

    //---------------------------------------------------------------------------- 
    // GetExceptionMessages 
    //---------------------------------------------------------------------------- 
    private static void GetExceptionMessages(Dictionary<string, string> i_dictExceptionMessage) 
    { 
    List<Type> listoExceptionType = GetExceptionTypes(); 
    for (int ixException = 0; ixException < listoExceptionType.Count; ixException++) 
    { 
     Type oExceptionType = listoExceptionType[ixException]; 
     string sExceptionName = MakeXMLCompliant(oExceptionType.FullName); 
     try 
     { 
     if (i_dictExceptionMessage.ContainsKey(sExceptionName)) 
      continue; 
     Exception e = (Exception)(Activator.CreateInstance(oExceptionType)); 
     i_dictExceptionMessage.Add(sExceptionName, e.Message); 
     } 
     catch (Exception) 
     { i_dictExceptionMessage.Add(sExceptionName, null); } 
    } 
    } 

    //---------------------------------------------------------------------------- 
    // GetExceptionMessagesWin32 
    //---------------------------------------------------------------------------- 
    private static void GetExceptionMessagesWin32(Dictionary<string, string> i_dictExceptionMessage) 
    { 
    string sTypeName = MakeXMLCompliant(typeof(Win32Exception).FullName) + "_"; 
    for (int iError = 0; iError < 0x4000; iError++) // Win32 errors may range from 0 to 0xFFFF 
    { 
     Exception e = new Win32Exception(iError); 
     if (!e.Message.StartsWith("Unknown error (", StringComparison.OrdinalIgnoreCase)) 
     i_dictExceptionMessage.Add(sTypeName + iError, e.Message); 
    } 
    } 

    //---------------------------------------------------------------------------- 
    // CreateMessage 
    //---------------------------------------------------------------------------- 
    private static string CreateMessage(Exception i_oException, CultureInfo i_oCultureInfo) 
    { 
    CException oEx = new CException(i_oException, i_oCultureInfo); 
    Thread oTH = new Thread(new ParameterizedThreadStart(CreateMessageInThread)); 
    oTH.Start(oEx); 
    while (oTH.IsAlive) 
    { Thread.Sleep(10); } 
    return oEx.m_sMessage; 
    } 

    //---------------------------------------------------------------------------- 
    // CreateMessageInThread 
    //---------------------------------------------------------------------------- 
    private static void CreateMessageInThread(Object i_oData) 
    { 
    if (i_oData == null) return; 
    CException oEx = (CException)i_oData; 
    if (oEx.m_oException == null) return; 

    Thread.CurrentThread.CurrentUICulture = oEx.m_oCultureInfo == null ? CultureInfo.InvariantCulture : oEx.m_oCultureInfo; 
    // create new exception in desired culture 
    Exception e = null; 
    Win32Exception oWin32Exception = (Win32Exception)(oEx.m_oException); 
    if (oWin32Exception != null) 
     e = new Win32Exception(oWin32Exception.NativeErrorCode); 
    else 
    { 
     try 
     { 
     e = (Exception)(Activator.CreateInstance(oEx.m_oException.GetType())); 
     } 
     catch { } 
    } 
    if (e != null) 
     oEx.m_sMessage = e.Message; 
    } 

    //---------------------------------------------------------------------------- 
    // MakeXMLCompliant 
    // from https://www.w3.org/TR/xml/ 
    //---------------------------------------------------------------------------- 
    private static string MakeXMLCompliant(string i_sName) 
    { 
    if (string.IsNullOrEmpty(i_sName)) 
     return "_"; 

    System.Text.StringBuilder oSB = new System.Text.StringBuilder(); 
    for (int ixChar = 0; ixChar < (i_sName == null ? 0 : i_sName.Length); ixChar++) 
    { 
     char character = i_sName[ixChar]; 
     if (IsXmlNodeNameCharacterValid(ixChar, character)) 
     oSB.Append(character); 
    } 
    if (oSB.Length <= 0) 
     oSB.Append("_"); 
    return oSB.ToString(); 
    } 

    //---------------------------------------------------------------------------- 
    private static bool IsXmlNodeNameCharacterValid(int i_ixPos, char i_character) 
    { 
    if (i_character == ':') return true; 
    if (i_character == '_') return true; 
    if (i_character >= 'A' && i_character <= 'Z') return true; 
    if (i_character >= 'a' && i_character <= 'z') return true; 
    if (i_character >= 0x00C0 && i_character <= 0x00D6) return true; 
    if (i_character >= 0x00D8 && i_character <= 0x00F6) return true; 
    if (i_character >= 0x00F8 && i_character <= 0x02FF) return true; 
    if (i_character >= 0x0370 && i_character <= 0x037D) return true; 
    if (i_character >= 0x037F && i_character <= 0x1FFF) return true; 
    if (i_character >= 0x200C && i_character <= 0x200D) return true; 
    if (i_character >= 0x2070 && i_character <= 0x218F) return true; 
    if (i_character >= 0x2C00 && i_character <= 0x2FEF) return true; 
    if (i_character >= 0x3001 && i_character <= 0xD7FF) return true; 
    if (i_character >= 0xF900 && i_character <= 0xFDCF) return true; 
    if (i_character >= 0xFDF0 && i_character <= 0xFFFD) return true; 
    // if (i_character >= 0x10000 && i_character <= 0xEFFFF) return true; 

    if (i_ixPos > 0) 
    { 
     if (i_character == '-') return true; 
     if (i_character == '.') return true; 
     if (i_character >= '0' && i_character <= '9') return true; 
     if (i_character == 0xB7) return true; 
     if (i_character >= 0x0300 && i_character <= 0x036F) return true; 
     if (i_character >= 0x203F && i_character <= 0x2040) return true; 
    } 
    return false; 
    } 

    private static string msc_sBaseFilename = "exception_messages"; 
    private static string msc_sXmlGroup_Root = "exception_messages"; 
    private static string msc_sXmlGroup_Info = "info"; 
    private static string msc_sXmlGroup_Messages = "messages"; 
    private static string msc_sXmlData_Culture = "culture"; 

    private Exception m_oException; 
    private CultureInfo m_oCultureInfo; 
    private string m_sMessage; 

    static Dictionary<CultureInfo, Dictionary<string, string>> ms_dictCultureExceptionMessages = new Dictionary<CultureInfo, Dictionary<string, string>>(); 
} 

internal class Program 
{ 
    public static void Main() 
    { 
    CException.CreateMessages(null); 
    CException.SaveMessagesToXML(@"d:\temp\", "emsg"); 
    CException.LoadMessagesFromXML(@"d:\temp\", "emsg"); 
    } 
} 
Смежные вопросы