Сообщения об исключениях на английском языке?

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

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

14 ответов


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

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

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

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


вы можете искать исходное сообщение об исключении вunlocalize.com


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

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

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


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

в en-US 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. Поскольку файлы французской культуры не установлены, по умолчанию используется Windows default (установлен?) язык.


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

это может быть не всегда применимо в каждом случае (это зависит от вашей настройки, поскольку вам нужно иметь возможность создать .конфигурационный файл в стороне от основного .EXE-файл), но это работает для меня. Итак, просто создайте app.config в dev (или [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, поэтому используйте на свой страх и риск. Ну, если вы обнаружите проблему, вы можете просто удалить эту конфигурацию и проверить, что она не связана.


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

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

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


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

Я бы себе один из этих подходов:

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

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


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:)


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

  1. сама .NET framework
  2. языковые пакеты .NET framework

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

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


у меня была такая же ситуация, и все ответы, которые я нашел здесь и в другом месте, не помогли или не удовлетворили:
исключений английского языка
C# - получение сообщений об исключениях на английском языке, когда приложение находится на другом языке?
как изменить язык сообщения об исключении Visual Studio на английский во время отладки
как обрабатывать перевод исключение сообщение?
как полностью избежать локализованных сообщений об исключениях .NET

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

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

статические функции этого класса могут выполняться на установках 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");
  }
}

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


переопределить сообщение об исключении в блоке 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();
        }

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

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

  1. изменяет текущую UICulture
  2. воссоздает брошенный объект исключения с помощью" Gettype () " & " активатор.CreateInstance (t)"
  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();
    
         }