345 Stimmen

Ausnahmemeldungen auf Englisch?

Wir protokollieren alle Ausnahmen, die in unserem System auftreten, indem wir die Exception.Message in eine Datei schreiben. Sie werden jedoch in der Kultur des Kunden geschrieben. Und türkische Fehler haben für mich keine große Bedeutung.

Wie können wir also Fehlermeldungen auf Englisch protokollieren, ohne die Benutzerkultur zu verändern?

80voto

mdb Punkte 50584

Dieses Problem kann teilweise umgangen werden. Der Ausnahmecode des Frameworks lädt die Fehlermeldungen aus seinen Ressourcen, basierend auf dem aktuellen Gebietsschema des Threads. Bei einigen Ausnahmen geschieht dies zum Zeitpunkt des Zugriffs auf die Eigenschaft Message.

In diesen Ausnahmefällen können Sie die vollständige US-englische Version der Nachricht erhalten, indem Sie das Gebietsschema des Threads während der Protokollierung kurz auf en-US umstellen (speichern Sie das ursprüngliche Benutzergebietsschema vorher und stellen Sie es unmittelbar danach wieder her).

Noch besser ist es, dies in einem separaten Thread zu tun: So wird sichergestellt, dass es keine Nebenwirkungen gibt. Zum Beispiel:

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

Die Klasse ExceptionLogger sieht in etwa so aus:

class ExceptionLogger
{
  Exception _ex;

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

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

Da jedoch Joe weist in einem Kommentar zu einer früheren Version dieser Antwort korrekterweise darauf hin, dass einige Meldungen zum Zeitpunkt des Auftretens der Ausnahme bereits (teilweise) aus den Sprachressourcen geladen sind.

Dies gilt für den Teil der Meldung "Parameter kann nicht null sein", der erzeugt wird, wenn z. B. eine ArgumentNullException("foo") ausgelöst wird. In diesen Fällen wird die Meldung immer noch (teilweise) lokalisiert angezeigt, selbst wenn der obige Code verwendet wird.

Außer durch die Verwendung von unpraktischen Hacks, wie z. B. alle Ihre Nicht-UI-Code auf einem Thread mit en-US locale zu beginnen, scheint es nicht viel Sie dagegen tun können: der .NET Framework-Ausnahmecode hat keine Möglichkeiten für die Fehlermeldung Gebietsschema überschreiben.

48voto

MPelletier Punkte 15633

Vielleicht ein strittiger Punkt, aber anstatt die Kultur auf en-US können Sie ihn auf Invariant . Im Invariant Kultur, die Fehlermeldungen sind in Englisch.

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

Sie hat den Vorteil, dass sie nicht voreingenommen wirkt, insbesondere für nicht-amerikanische englischsprachige Länder. (auch um abfällige Bemerkungen von Kollegen zu vermeiden)

19voto

Simon Mourier Punkte 122836

Hier ist eine Lösung, die kein Coding erfordert und sogar für Texte von Ausnahmen funktioniert, die zu früh geladen werden, als dass wir sie durch Code ändern könnten (z. B. die in mscorlib).

Es ist vielleicht nicht in jedem Fall anwendbar (es hängt von Ihrem Setup ab, da Sie in der Lage sein müssen, eine .config-Datei neben der Haupt-.exe-Datei zu erstellen), aber das funktioniert bei mir. Erstellen Sie also einfach eine app.config in dev, (oder ein [myapp].exe.config o web.config in der Produktion), die beispielsweise die folgenden Zeilen enthält:

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

Dadurch wird das Framework angewiesen, die Assembly-Bindings für mscorlib die Ressourcen des Unternehmens und System.Xml für Versionen zwischen 1 und 999, in französischer Sprache (Kultur ist auf " fr ") zu einer Baugruppe, die ... nicht existiert (eine beliebige Version 999).

Wenn die CLR also nach französischen Ressourcen für diese beiden Assemblies (mscorlib und System.xml) sucht, wird sie diese nicht finden und elegant auf Englisch zurückgreifen. Abhängig von Ihrem Kontext und Ihren Tests, möchten Sie vielleicht andere Baugruppen zu diesen Umleitungen hinzufügen (Baugruppen, die lokalisierte Ressourcen enthalten).

Natürlich glaube ich nicht, dass dies von Microsoft unterstützt wird, die Verwendung erfolgt also auf eigene Gefahr. Falls Sie ein Problem feststellen, können Sie diese Konfiguration einfach entfernen und überprüfen, ob es keinen Zusammenhang gibt.

13voto

danobrega Punkte 111

Unter Windows muss die gewünschte Sprache der Benutzeroberfläche installiert sein. Ist dies nicht der Fall, kann es nicht auf magische Weise wissen, wie die übersetzte Nachricht lautet.

In einem en-US Windows 7 ultimate mit installiertem pt-PT wird der folgende Code angezeigt:

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;

Erzeugt Nachrichten in pt-PT, en-US und en-US. Da keine französischen Kulturdateien installiert sind, wird standardmäßig die (installierte?) Windows-Standardsprache verwendet.

6voto

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;

Ohne WORKAROUNDS.

Tks :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X