IT

영어로 된 예외 메시지?

lottoking 2020. 3. 21. 10:47

영어로 된 예외 메시지?


Exception.Message를 파일에 작성하여 시스템에서 발생하는 모든 예외를 로깅합니다. 그러나 그들은 고객의 문화로 작성되었습니다. 터키의 실수는 나에게 큰 의미가 없습니다.

그렇다면 사용자 문화를 바꾸지 않고 어떻게 오류 메시지를 영어로 기록 할 수 있습니까?


이 문제는 부분적으로 해결 될 수 있습니다. 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") 예외가 발생할 때 생성 된 메시지의 '매개 변수가 널일 수 없음'부분에 적용됩니다. 이러한 경우 위의 코드를 사용하더라도 메시지가 여전히 부분적으로 현지화되어 나타납니다.

en-US 로케일이있는 스레드에서 모든 비 UI 코드를 실행하는 등 실용적이 아닌 해킹을 사용하는 것 외에는 할 수있는 일이 많지 않습니다. .NET Framework 예외 코드에는 오류 메시지 로캘을 재정의하는 기능


unlocalize.com 에서 원래 예외 메시지를 검색 할 수 있습니다.


논쟁의 여지가 있지만 문화를로 설정하는 대신로 설정할 en-US수 있습니다 Invariant. 에서 Invariant문화, 오류 메시지가 영어로되어 있습니다.

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

비 미국 영어권 지역에서는 편향적으로 보이지 않는 장점이 있습니다. (일명 동료의 비난을 피함)


Windows에는 사용하려는 UI 언어가 설치되어 있어야합니다. 번역 된 메시지가 무엇인지 마술처럼 알 수있는 방법은 없습니다.

pt-PT가 설치된 en-US Windows 7 Ultimate에서 다음 코드는 다음과 같습니다.

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 기본 (설치?) 언어가 사용됩니다.


여기에는 코딩이 필요하지 않으며 너무 일찍로드 된 예외 텍스트 (예 : mscorlib의 텍스트)로 변경할 수없는 예외 텍스트에도 작동하는 솔루션이 있습니다.

모든 경우에 항상 적용 가능한 것은 아니지만 (주 .exe 파일과 함께 .config 파일을 만들 수 있어야하기 때문에 설정에 따라 다릅니다) 그러나 그것은 저에게 효과적입니다. 따라서 예를 들어 다음과 같은 줄이 포함 app.configin dev (또는 a [myapp].exe.config또는 web.configproduction)를 만드십시오 .

<configuration>
  ...
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="mscorlib.resources" publicKeyToken="b77a5c561934e089"
                          culture="fr" /> <!-- change this to your language -->

        <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" /> <!-- change this to your language -->

        <bindingRedirect oldVersion="1.0.0.0-999.0.0.0" newVersion="999.0.0.0"/>
      </dependentAssembly>

      <!-- add other assemblies and other languages here -->

    </assemblyBinding>
  </runtime>
  ...
</configuration>

이 작업은 프레임 워크가 프랑스어 (문화는 " " 로 설정 됨)에서 프랑스어 (문화는 " " 로 설정 됨 )에서 존재하지 않는 (임의의) 임의의 (임의 mscorlib의) 리소스 및 리소스에 대한 어셈블리 바인딩을 리디렉션 하도록 지시합니다. 버전 999).System.Xmlfr

따라서 CLR이이 두 어셈블리 (mscorlib 및 System.xml)에 대한 프랑스어 리소스를 찾을 때는 찾지 못하고 정상적으로 영어로 대체됩니다. 상황과 테스트에 따라 이러한 리디렉션 (현지화 된 리소스가 포함 된 어셈블리)에 다른 어셈블리를 추가 할 수 있습니다.

물론 이것이 Microsoft에서 지원한다고 생각하지 않으므로 자신의 책임하에 사용하십시오. 문제를 발견 한 경우이 구성을 제거하고 관련이 없는지 확인할 수 있습니다.


나는 이것이 오래된 주제라는 것을 알고 있지만 내 솔루션은 웹 검색에서 우연히 발견되는 사람과 관련이 있다고 생각합니다.

예외 로거에서 ex.GetType.ToString을 기록하면 예외 클래스의 이름이 저장됩니다. 클래스의 이름은 언어와 독립적이어야하므로 항상 영어로 표시 될 것으로 예상합니다 (예 : "System.FileNotFoundException"). 현재로서는 외국어 시스템에 액세스하여 테스트 할 수는 없습니다. 생각.

오류 메시지 텍스트를 정말로 원한다면 가능한 모든 예외 클래스 이름과 동등한 메시지의 사전을 원하는 언어로 만들 수 있지만 영어의 경우 클래스 이름이 완벽하다고 생각합니다.


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
}

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 프레임 워크는 두 부분으로 구성됩니다.

  1. .NET 프레임 워크 자체
  2. .NET 프레임 워크 언어 팩

모든 텍스트 (예 : 예외 메시지, MessageBox의 단추 레이블 등)는 .NET 프레임 워크 자체에서 영어로되어 있습니다. 언어 팩에는 현지화 된 텍스트가 있습니다.

정확한 상황에 따라 해결 방법은 언어 팩을 제거하는 것입니다 (예 : 클라이언트에게 그렇게하도록 지시). 이 경우 예외 텍스트는 영어입니다. 그러나 다른 모든 프레임 워크 제공 텍스트도 영어입니다 (예 : MessageBox의 단추 레이블, ApplicationCommands의 키보드 단축키).


나는 이러한 접근법 중 하나를 상상할 것이다.

1) 예외는 사용자 만 읽을 수 있습니다. 즉, 클라이언트 기능이 아니므로 터키어 모드에서 실행할 때 변경되지 않은 현지화 된 문자열이 아닌 문자열을 사용할 수 있습니다.

2) 오류 코드를 포함하십시오. 영어 테이블에서 쉽게 찾을 수 있도록 각 오류와 함께 0X00000001.


나는 같은 상황을 겪었고 여기와 다른 곳에서 찾은 모든 대답이 도움이되지 않거나 만족스럽지 못했습니다.
영어로 강제 예외 언어
C #-응용 프로그램이 다른 언어 일 때 영어로 예외 메시지 받기?
디버깅
하는 동안 Visual Studio 예외 메시지 언어를 영어로 변경하는 방법 예외 메시지의 번역을 처리하는 방법은 무엇입니까?
지역화 된 .NET 예외 메시지를 완전히 피하는 방법

Thread.CurrentUICulture그물 예외의 언어를 변경하지만,하지의 경우와 Win32Exception윈도우 UI 자체의 언어로 윈도우 리소스를 사용한다. 그래서 Win32Exception영어 FormatMessage()Win32Exception을 얻는 방법에서 설명한대로 조차 사용하지 않고 독일어 대신 영어로 메시지를 인쇄 하지 못했습니다
.

따라서 다른 언어에 대한 대부분의 기존 예외 메시지를 외부 파일에 저장하는 자체 솔루션을 만들었습니다. 원하는 언어로 정확한 메시지를 얻을 수는 없지만 현재 언어보다 훨씬 많은 언어로 된 메시지를 볼 수 있습니다 (이해할 수없는 언어로 된 메시지).

이 클래스의 정적 함수는 다른 언어를 사용하는 Windows 설치에서 실행될 수 있습니다 CreateMessages(). 문화권 별 텍스트를 작성
SaveMessagesToXML()하면 언어가 작성되거나로드 될 때마다 많은 XML 파일에이를 저장하고
LoadMessagesFromXML()언어 별 메시지가있는 모든 XML 파일을로드합니다.

다른 언어로 다른 Windows 설치에서 XML 파일을 작성할 때 필요한 모든 언어가 곧 제공 될 것입니다.
여러 MUI 언어 팩이 설치되어있을 때 1 Windows에서 다른 언어의 텍스트를 만들 수는 있지만 아직 테스트하지는 않았습니다.

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

Undercover1989 답변을 기반으로하지만 매개 변수 및 메시지가 인수 예외와 같은 여러 리소스 문자열로 구성된시기를 고려합니다.

public static string TranslateExceptionMessage(Exception exception, CultureInfo targetCulture)
{
    Assembly a = exception.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);

    var result = exception.Message;

    foreach (DictionaryEntry item in rsOriginal)
    {
        if (!(item.Value is string message))
            continue;

        string translated = rsTranslated.GetString(item.Key.ToString(), false);

        if (!message.Contains("{"))
        {
            result = result.Replace(message, translated);
        }
        else
        {
            var pattern = $"{Regex.Escape(message)}";
            pattern = Regex.Replace(pattern, @"\\{([0-9]+)\}", "(?<group$1>.*)");

            var regex = new Regex(pattern);

            var replacePattern = translated;
            replacePattern = Regex.Replace(replacePattern, @"{([0-9]+)}", @"${group$1}");
            replacePattern = replacePattern.Replace("\\$", "$");

            result = regex.Replace(result, replacePattern);
        }
    }

    return result;
}

오류 메시지 대신 호출 스택을 기록해야합니다 (IIRC, simple exception.ToString ()이 대신해야합니다). 여기에서 예외가 발생한 위치를 정확하게 판별하고 일반적으로 예외를 추론 할 수 있습니다.


확장 방법을 사용하여 catch 블록에서 예외 메시지를 재정의합니다. Check thrown message는 코드에서 발생했는지 또는 아래 언급되지 않은 것입니다.

    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 ()"& "Activator.CreateInstance (t)"를 사용하여 throw 된 Exception 객체를 다시 만듭니다.
  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();
    
         }
    

참고 URL : https://stackoverflow.com/questions/209133/exception-messages-in-english