Question

Nous enregistrons toutes les exceptions qui se produisent dans notre système en écrivant le message Exception.Message dans un fichier. Cependant, ils sont écrits dans la culture du client. Et les erreurs turques ne signifient pas grand chose pour moi.

Alors, comment pouvons-nous consigner des messages d'erreur en anglais sans changer la culture des utilisateurs?

Était-ce utile?

La solution

Ce problème peut être partiellement résolu. Le code d'exception du Framework charge les messages d'erreur à partir de ses ressources, en fonction des paramètres régionaux du thread actuel. Dans le cas de certaines exceptions, cela se produit au moment de l'accès à la propriété Message.

Pour ces exceptions, vous pouvez obtenir la version anglaise complète du message en commutant brièvement l'environnement local du thread sur en-US lors de la journalisation (enregistrement préalable de l'environnement local de l'utilisateur et restauration de celui-ci immédiatement après).

Faire ceci sur un thread séparé est encore mieux: cela garantit qu’il n’y aura pas d’effets secondaires. Par exemple:

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

Où la classe ExceptionLogger ressemble à quelque chose comme:

class ExceptionLogger
{
  Exception _ex;

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

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

Toutefois, comme Joe indique correctement dans un commentaire sur une révision antérieure de cette réponse, certains messages sont déjà ( partiellement) chargé depuis les ressources linguistiques au moment de la levée de l'exception.

Ceci s'applique au paramètre 'ne peut pas être null' dans le message généré lorsqu'une exception ArgumentNullException ("foo") est levée, par exemple. Dans ces cas, le message apparaîtra (partiellement) toujours localisé, même si vous utilisez le code ci-dessus.

À part l'utilisation de hacks peu pratiques, tels que l'exécution de tout votre code non-UI sur un thread avec des paramètres régionaux en-US, il ne semble pas y avoir grand-chose que vous puissiez faire à ce sujet: l'exception .NET Framework le code n'a aucune possibilité de remplacer les paramètres régionaux du message d'erreur.

Autres conseils

Vous pouvez rechercher le message d'exception d'origine à l'adresse unlocalize.com

.

Un point litigieux peut-être, mais au lieu de définir la culture sur en-US , vous pouvez la définir sur Invariant . Dans la culture Invariant , les messages d'erreur sont en anglais.

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

Il présente l’avantage de ne pas sembler partial, en particulier pour les localités anglophones non américaines. (ak.a. évite les remarques sournoises de collègues)

Windows doit disposer de la langue de l'interface utilisateur que vous souhaitez utiliser. Si ce n’est pas le cas, il n’a aucun moyen de savoir comme par magie quel est le message traduit.

Dans Windows 7 Ultimate en-US, avec pt-PT installé, le code suivant:

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;

Produit des messages en pt-PT, en-US et en-US. Puisqu'aucun fichier de culture française n'est installé, il utilise par défaut la langue par défaut de Windows (installé?).

Voici une solution qui ne nécessite aucun codage et fonctionne même pour les textes d'exceptions chargés trop tôt pour pouvoir être modifiés par code (par exemple, ceux de mscorlib).

Cela peut ne pas être toujours applicable dans tous les cas (cela dépend de votre configuration car vous devez être capable de créer un fichier .config en plus du fichier .exe principal), mais cela fonctionne pour moi. Il suffit donc de créer un app.config dans dev (ou un [myapp] .exe.config ou un web.config en production) qui contient par exemple les lignes suivantes:

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

Cela indique au framework de rediriger les liaisons d'assembly pour les ressources de mscorlib et pour les ressources de System.Xml , pour les versions comprises entre 1 et 999. (culture est définie sur " fr ") dans un assemblage qui ... n'existe pas (version arbitraire 999).

Ainsi, lorsque le CLR recherchera des ressources en français pour ces deux assemblys (mscorlib et System.xml), il ne les trouvera pas et se repliera gracieusement en anglais. En fonction de votre contexte et de vos tests, vous souhaiterez peut-être ajouter d'autres assemblys à ces redirections (assemblys contenant des ressources localisées).

Bien sûr, je ne pense pas que cela soit supporté par Microsoft, utilisez-le à vos risques et périls. Eh bien, si vous détectez un problème, vous pouvez simplement supprimer cette configuration et vérifier qu’elle n’est pas liée.

Je sais que c'est un sujet ancien, mais je pense que ma solution peut être tout à fait pertinente pour tous ceux qui tombent dans une recherche sur le Web:

Dans le journal des exceptions, vous pouvez enregistrer ex.GetType.ToString, ce qui enregistrerait le nom de la classe des exceptions. Je m'attendrais à ce que le nom d'une classe soit indépendant de la langue et par conséquent toujours représenté en anglais (par exemple, "System.FileNotFoundException"), bien qu'à l'heure actuelle, je n'ai pas accès à un système de langues étrangères pour tester l'idée.

Si vous voulez vraiment le texte du message d'erreur, vous pouvez créer un dictionnaire de tous les noms de classe d'exception possibles et de leurs messages équivalents dans la langue de votre choix, mais pour l'anglais, je pense que le nom de la classe convient parfaitement.

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;

Sans les WORKAROUNDS.

Tks :))

Le cadre .NET comprend deux parties:

  1. Le framework .NET lui-même
  2. Les modules de langue du framework .NET

Tous les textes (ex. messages d'exception, étiquettes de bouton sur une MessageBox, etc.) sont en anglais dans le framework .NET même. Les packs de langue ont les textes localisés.

En fonction de votre situation exacte, une solution serait de désinstaller les packs de langue (par exemple, indiquez au client de le faire). Dans ce cas, les textes d’exception seront en anglais. Notez toutefois que tous les autres textes fournis par la structure seront également en anglais (par exemple, les libellés de boutons sur une boîte de message, les raccourcis clavier pour les commandes d'applications).

La définition de Thread.CurrentThread.CurrentUICulture sera utilisée pour localiser les exceptions. Si vous avez besoin de deux types d'exceptions (une pour l'utilisateur, une pour vous), vous pouvez utiliser la fonction suivante pour traduire le message d'exception. Il cherche dans les ressources .NET-Libraries le texte original pour obtenir la clé de ressource, puis renvoie la valeur traduite. Mais il y a une faiblesse pour laquelle je n'ai pas encore trouvé de bonne solution: les messages contenant {0} de ressources ne seront pas trouvés. Si quelqu'un avait une bonne solution, je vous en serais reconnaissant.

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
}

J'imagine l'une de ces approches:

1) Les exceptions ne sont lues que par vous, c’est-à-dire qu’elles ne sont pas une fonctionnalité client. Vous pouvez donc utiliser des chaînes câblées non localisées qui ne changeront pas lorsque vous vous exécuterez en mode turc.

2) Inclure un code d'erreur, par exemple. 0X00000001 avec chaque erreur afin que vous puissiez facilement la rechercher dans un tableau anglais.

J'ai eu la même situation et toutes les réponses que j'ai trouvées ici et ailleurs n'ont pas aidé ou n'ont pas été satisfaisantes:
Forcer le langage des exceptions en anglais
C # - Obtention des messages d'exception dans Anglais lorsque l'application est dans une autre langue?
Comment modifier le langage du message d'exception de Visual Studio en anglais lors du débogage
Comment gérer la traduction du message d'exception?
Comment éviter complètement les messages d'exception .NET localisés

Le Thread.CurrentUICulture modifie la langue des exceptions .net, mais pas le Win32Exception , qui utilise les ressources Windows dans la langue de l'interface utilisateur Windows elle-même. Je n’ai donc jamais réussi à imprimer les messages de Win32Exception en anglais au lieu de l’allemand, pas même en utilisant FormatMessage () comme décrit dans
Comment obtenir Win32Exception en anglais?

J'ai donc créé ma propre solution, qui stocke la majorité des messages d'exception existants pour différentes langues dans des fichiers externes. Vous ne recevrez pas le message très exact dans la langue de votre choix, mais un message dans cette langue, qui est bien plus que ce que vous recevez actuellement (message dans une langue que vous ne comprenez probablement pas).

Les fonctions statiques de cette classe peuvent être exécutées sur des installations Windows avec différentes langues: CreateMessages () crée les textes propres à la culture

SaveMessagesToXML () les enregistre dans autant de fichiers XML que de langues créées ou chargées

LoadMessagesFromXML () charge tous les fichiers XML avec des messages spécifiques à la langue

Lors de la création de fichiers XML sur différentes installations Windows avec différentes langues, vous aurez bientôt toutes les langues dont vous avez besoin.
Peut-être pouvez-vous créer des textes pour différentes langues sur 1 Windows lorsque plusieurs packs de langue MUI sont installés, mais je ne l'ai pas encore testé.

Testé avec VS2008, prêt à être utilisé. Vos commentaires et suggestions sont les bienvenus!

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

Sur la base de la réponse Undercover1989, mais prend en compte les paramètres et lorsque les messages sont composés de plusieurs chaînes de ressources (comme des exceptions d'arguments).

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 = <*>quot;{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("\\<*>quot;, "<*>quot;);

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

    return result;
}

Vous devriez enregistrer la pile d'appels au lieu d'un simple message d'erreur (IIRC, simple exception.ToString () devrait le faire pour vous). À partir de là, vous pouvez déterminer exactement d'où provient l'exception et généralement en déduire de quelle exception il s'agit.

Remplacer le message d'exception dans le bloc catch à l'aide de la méthode d'extension. Le message Vérifier que le message est levé provient du code ou non, comme indiqué ci-dessous.

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

À des fins de journalisation, certaines applications peuvent avoir besoin de récupérer le message d’exception anglais (en plus de l’afficher dans UICulture du client habituel).

Pour cela, le code suivant

  1. change le UICulture actuel
  2. recrée l'objet Exception levé à l'aide de "GetType ()". & amp; "Activator.CreateInstance (t)"
  3. affiche le nouveau message de l'objet Exception dans la nouvelle UICuture
  4. , puis modifie finalement l'UICulture en cours pour revenir à l'ancienne 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();
    
         }
    
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top