İngilizce istisna mesajları?


298

Bir dosyaya Exception.Message yazarak sistemimizde meydana gelen istisnaları günlüğe kaydediyoruz. Ancak, müşterinin kültüründe yazılırlar. Ve Türk hataları benim için çok önemli değil.

Peki, kullanıcı kültürünü değiştirmeden İngilizce herhangi bir hata mesajını nasıl kaydedebiliriz?


8
Neden böyle swift yapamıyorsunuz: CultureInfo oldCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture ("en"); // yeni atmak İstisna burada => Kültür İngilizcedir Thread.CurrentThread.CurrentCulture = oldCulture;
CheGueVerra

93
Ben hiçbir geliştirici biliyorum, ingilizce olmayan istisna mesajlar için mutlu: S. ..
Zéiksz

3
@ Zéiksz İngilizce konuşulan ülkelerin ötesine bakın ve birçoğunu bulacaksınız: D. Sorun İngilizce olmayan bir metin değil, sorun anlayamadığınız bir dildir. Ana dilinizdeki mesajlar (uygun çeviri olduğu varsayılarak) son derece iyi durumda.
Alejandro

31
@Alejandro Google'a bir istisna mesajını bir ana dilden ingilizceye çevirmek zorunda kalmak, kıçta daha büyük bir acıdır. Benim nacizane fikrime göre.
Antoine Meltzheim

18
Microsoft'taki hangi salak sadece geliştiriciler için olan hata mesajlarını tercüme etme fikrine sahipti. Programlama dilinde kullanılan ve sözlükte bir anahtar gibi kullanılan terimler bile çevrilir. (Anahtar sözlükte bulunmaz Hollandaca de bibliotheek niet gevonden de Sleutel olur). Bunun için işletim sistemi dilini değiştirmek istemiyorum ...
Roel

Yanıtlar:


66

Bu sorun kısmen çözülebilir. Framework özel durum kodu, geçerli iş parçacığı yerel ayarına bağlı olarak hata iletilerini kaynaklarından yükler. Bazı istisnalar söz konusu olduğunda, bu, Message özelliğine erişildiğinde gerçekleşir.

Bu istisnalar için, oturum açarken iş parçacığı yerel ayarını kısaca en-US olarak değiştirerek iletinin tam ABD İngilizcesi sürümünü edinebilirsiniz (orijinal kullanıcı yerel ayarını önceden kaydedip hemen sonra geri yükleyebilirsiniz).

Bunu ayrı bir iplik üzerinde yapmak daha da iyidir: bu, herhangi bir yan etki olmayacağını garanti eder. Örneğin:

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 sınıfı aşağıdaki gibi görünür:

class ExceptionLogger
{
  Exception _ex;

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

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

Bununla birlikte, Joe bu cevabın daha önceki bir revizyonu hakkındaki bir yorumda doğru bir şekilde işaret ettiğinden, bazı mesajlar istisna atıldığında dil kaynaklarından zaten (kısmen) yüklenmiştir.

Bu, örneğin bir ArgumentNullException ("foo") istisnası atıldığında oluşturulan iletinin 'parametresi boş olamaz' kısmı için geçerlidir. Bu durumlarda, yukarıdaki kod kullanılırken bile ileti yerel olarak görünmeye devam eder (kısmen).

UI olmayan tüm kodlarınızı en-US yerel ayarına sahip bir iş parçacığında çalıştırmak gibi pratik olmayan kesmek kullanmak dışında, bununla ilgili yapabileceğiniz çok fazla bir şey görünmüyor: .NET Framework istisna kodu yok hata mesajı yerel ayarını geçersiz kılma tesisleri.


10
Örneğiniz bir FileNotFoundException için çalışır, çünkü Message özelliğine erişildiğinde değil, özel durum atıldığında değil, ileti kaynağı alınır. Ancak bu, tüm istisnalar için geçerli değildir (örn. Yeni ArgumentNullException ("paramName") atmayı deneyin)
Joe

3
Kafam karıştı. Cevabınızı takip etmeyi denedim ve test etmek için t.CurrentUICulture = new System.Globalization.CultureInfo("fr-FR");t.CurrentCulture = new System.Globalization.CultureInfo("fr-FR");
istisnamı

7
@VitalyB Yerelleştirilmiş özel durum metinleri, .NET framework dil paketlerinin bir parçasıdır. Fransızca dil paketiniz yüklü değilse, çevrilmiş metinleri alamazsınız.
Daniel Rose

7
En azından .NET 4.5 ile, tüm istisnalar somutlaştırılır, Environment.GetResourceString("...")böylece çözümünüz artık çalışmaz. En iyi şey, kendi (ingilizce) mesaj metninizle özel istisna atmak ve eskisini tutmak için InnerException özelliğini kullanmaktır.
webber2k6

1
İstisna türü adlarını alma yansıması kullanışlı olabilir.
Guillermo Prandi

67

Orijinal istisna mesajını unlocalize.com adresinde arayabilirsiniz.


5
Bana bazı Çin istisna mesajlarını aramayı denedim No records found.
Tyler Long

1
Kötü seçim. İstisnalarımı Google Analytics'e (veya başka bir bulut hizmetine) gönderdiğimde, aynı istisna için farklı istisna gruplarına, ancak farklı dillere sahip olacağım. Ve her istisnanın sayısına göre sıralayamayacağım, çünkü gerçek sayımı yansıtmıyor (100 İngilizce, Çince 77, Korece 80 ... vb.)
Artemious

Google'a yerelleştirilmiş özel durum mesajlarını döktüğümde bu güzel web sitesini birçok kez bulmayı hatırlıyorum, artık mevcut değil.
Martin Braun

40

Çekişmeli bir nokta belki, ancak kültürü ayarlamak yerine en-USonu ayarlayabilirsiniz Invariant. In Invariantkültür, hata iletileri İngilizce'dir.

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

Özellikle Amerikan İngilizcesi olmayan yerel bölgeler için önyargılı görünmeme avantajına sahiptir. (aka meslektaşlardan gelen gizli açıklamalardan kaçınır)


1
Bu satırları ASP.NET projemize nereye yazmalıyız? Teşekkürler.
jason

2
Application_Start'ta en üstte önereceğim. Bu, tüm projenin İngilizce çalışmasını sağlayacaktır. Yalnızca istediğiniz hata iletileri içinse, bir kapak işlevi yapabilir ve her birinde çağırabilirsiniz catch.
MPelletier

5
Bu aynı zamanda standart mesaj kutusu düğmelerinin İngilizce olmasını sağlamaz mı? Bu istenen davranış olmayabilir.
Nyerguds

12

Kodlama gerektirmeyen ve kodla değiştirebilmemiz için çok erken yüklenen istisna metinleri için bile çalışan çözüm (örneğin, mscorlib'de olanlar).

Her durumda her zaman geçerli olmayabilir (ana .exe dosyasını bir kenara bir .config dosyası oluşturmanız gerektiğinden kurulumunuza bağlıdır) ancak bu benim için çalışır. Bu nedenle, örneğin aşağıdaki satırları içeren bir app.configin dev (veya bir [myapp].exe.configveya web.configüretimde) oluşturun:

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

Bunun yaptığı, 1 ve 999 arasındaki sürümler için Fransızca'nın (kültür " " olarak ayarlanmış ) sürümleri için mscorlibkaynakların ve kaynakların derleme bağlarını ... olmayan bir düzene yeniden yönlendirmek için çerçeveye anlatmaktır. sürüm 999).System.Xmlfr

Dolayısıyla CLR bu iki derleme (mscorlib ve System.xml) için Fransızca kaynaklar aradığında, bunları bulamaz ve incelikle İngilizce'ye geri dönmez. Bağlamınıza ve testlerinize bağlı olarak, bu yönlendirmelere (yerelleştirilmiş kaynaklar içeren montajlar) başka montajlar eklemek isteyebilirsiniz.

Elbette bunun Microsoft tarafından desteklendiğini düşünmüyorum, bu nedenle kendi sorumluluğunuzdadır. Bir sorun tespit etmeniz durumunda, bu yapılandırmayı kaldırabilir ve alakasız olup olmadığını kontrol edebilirsiniz.


1
Test koşucusu araçlarından ingilizce çıktı gerektiğinde çalışır.
smg

Bunu denedim, ama benim için işe yaramadı. .Net dosyasında başka kaynak dosyaları var mı? Onları nerede bulabilirim?
BluE

1
C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 dosyasına bakın. Her dilin 2 harfli bir klasörü vardır. Yukarıdaki cevaptaki "fr" ifadesini kullanılan gerçek dil ile değiştirmeyi unutmayın. norveççe için "hayır",
danca

TAM liste oluşturmak için bu klasöre bir göz atın. Yaklaşık 120 kaynak dosyası. Her birini yapılandırmaya ekleyin. .Net dil paketlerini artık yeni pencerelerde (işletim sisteminin bir parçası) kaldırmanın bir yolu olmadığından, bu, Windows 10 ve daha yeni sürümler için tek çözüm gibi görünüyor. Hatta şimdi GAC'a yerleştirildi, bu yüzden bu dil klasörlerini kaldırmak işe yaramıyor gibi görünüyor.
Wolf5

10

Windows'un kullanmak istediğiniz UI dilinin yüklü olması gerekir. Çevrilmemiş mesajın ne olduğunu sihirli bir şekilde bilmenin bir yolu yoktur.

En-US Windows 7 Ultimate'da, PT-PT kurulu olarak aşağıdaki kod:

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 ve en-US'de mesaj üretir. Yüklü bir Fransız kültür dosyası olmadığından, varsayılan olarak Windows varsayılan (kurulu?) Dili kullanılır.


Sorun çözüldü. Benim durumumda Lehçe UI, Vistalizator programını kullanarak en MUI dil paketleri ~ 260MB yükledi.
Krzysztof Szynter

5

Bunun eski bir konu olduğunu biliyorum, ancak benim çözümümün bir web aramasında tökezleyen herkes için oldukça alakalı olabileceğini düşünüyorum:

İstisna günlüğünde, istisna sınıfının adını kaydedecek olan ex.GetType.ToString günlüğünü kaydedebilirsiniz. Bir sınıfın adının dilden bağımsız olması ve bu nedenle her zaman İngilizce olarak temsil edilmesini bekliyorum (örneğin, "System.FileNotFoundException"), ancak şu anda bir yabancı dil sistemine erişimim yok fikir.

Hata mesajı metnini de gerçekten istiyorsanız, istediğiniz dilin tüm istisna sınıfı adlarının ve eşdeğer mesajlarının sözlüğünü oluşturabilirsiniz, ancak İngilizce için sınıf adının mükemmel olduğunu düşünüyorum.


5
Çalışmıyor. Bir var InvalidOperationExceptiontarafından atılan, System.Xml.XmlWellFormedWriter. İletiyi okumadan hangi hatanın oluştuğunu tahmin etmeye çalışırsınız. Bin farklı şey olabilir.
Nyerguds

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

GEÇİCİ ÇÖZÜM YOK.

Tks :)


unuttun;
KansaiRobot

4

Ayar Thread.CurrentThread.CurrentUICultureistisnaları yerelleştirmek için kullanılacaktır. İki tür istisnaya ihtiyacınız varsa (biri kullanıcı, biri sizin için) istisna mesajını çevirmek için aşağıdaki işlevi kullanabilirsiniz. .NET anahtarları kaynak anahtarını almak ve sonra çevrilen değeri döndürmek için özgün metni arar. Ancak henüz iyi bir çözüm bulamadığım bir zayıf nokta var: Kaynaklarda {0} içeren mesajlar bulunamıyor. Eğer birinin iyi bir çözümü varsa minnettar olurum.

public static string TranslateExceptionMessage(Exception ex, CultureInfo targetCulture)
{
    try
    {
        Assembly assembly = ex.GetType().Assembly;
        ResourceManager resourceManager = new ResourceManager(assembly.GetName().Name, assembly);
        ResourceSet originalResources = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, createIfNotExists: true, tryParents: true);
        ResourceSet targetResources = resourceManager.GetResourceSet(targetCulture, createIfNotExists: true, tryParents: true);
        foreach (DictionaryEntry originalResource in originalResources)
            if (originalResource.Value.ToString().Equals(ex.Message.ToString(), StringComparison.Ordinal))
                return targetResources.GetString(originalResource.Key.ToString(), ignoreCase: false); // success

    }
    catch { }
    return ex.Message; // failed (error or cause it's not smart enough to find texts with '{0}'-patterns)
}

İstisna biçimlendirilmiş bir parametre içeriyorsa bu çalışmaz.
Nick Berardi

Evet, dediğim gibi: "Ama henüz iyi bir çözüm bulamadım. Bir zayıflık var: Kaynaklarda {0} içeren mesajlar bulunmayacak. Eğer iyi bir çözüm varsa, minnettar olurum."
Vortex852456

3

.NET çerçevesi iki bölümden oluşur:

  1. .NET çerçevesinin kendisi
  2. .NET framework dil paketleri

Tüm metinler (istisna mesajları, MessageBox üzerindeki düğme etiketleri vb.) .NET çerçevesinin kendisinde İngilizce'dir. Dil paketleri yerelleştirilmiş metinlere sahiptir.

Kesin durumunuza bağlı olarak, bir çözüm dil paketlerini kaldırmak olacaktır (yani istemciye bunu yapmasını söyleyin). Bu durumda, istisna metinler İngilizce olacaktır. Bununla birlikte, diğer tüm çerçeve tarafından sağlanan metinlerin de İngilizce olacağını unutmayın (örneğin, bir MessageBox üzerindeki düğme etiketleri, ApplicationCommands için klavye kısayolları).


Teşekkürler!! Kaldırma iletişim kutusunun yerel dil değil, kaldırma paketinin dilinde olduğunu ironik buluyorum. Yan not: Dil paketleri birkaç ayda bir geri dönüyor gibi görünüyor. neden çalışmadım ama bir güncelleme / yükseltme tahmin
Choco Smith

@ChocoSmith Windows Update aracılığıyla her .NET Framework güncellemesinde dil paketi yeniden yüklenir.
Daniel Rose

5
Müşterilerden kendi dilleri için dil paketlerini kaldırmasını istemek uygun bir çözüm değildir.
Nyerguds

2

Bu yaklaşımlardan birini hayal ediyorum:

  1. İstisnalar sadece sizin tarafınızdan okunur, yani bir istemci özelliği değildir, bu nedenle Türkçe modunda çalıştırıldığında değişmeyecek kablolu yerelleştirilmemiş dizeleri kullanabilirsiniz.

  2. 0x00000001İngilizce bir tabloda kolayca bakabilmeniz için her hataya bir hata kodu ekleyin .


9
Bu , .net çerçevesinin iç bileşenleri tarafından atılan istisnalar olduğunda çok yardımcı olmaz . Tüm bu sorun , kendinizi attığınız istisnalar için geçerli değildir ; Açıkçası ne mesaj programcı seçer dahil etmek olanlar .
Nyerguds

1

Undercover1989 cevabını temel alır, ancak parametreleri ve mesajların birkaç kaynak dizesinden oluştuğunu (bağımsız değişken istisnaları gibi) dikkate alır.

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

1

Aynı duruma sahiptim ve burada ve başka yerlerde bulduğum tüm cevaplar yardımcı olmadı veya tatmin edici değildi:

Thread.CurrentUICulture.Net istisnalar dilini değiştirir, ama değildi için yaptığı Win32ExceptionWindows kullanıcı arabiriminde kendisinin dilde Windows kaynaklarını kullanan,. Bu yüzden mesajları yazdırmak için yönetilen asla Win32Exceptiondeğil, hatta kullanılarak yerine İngilizce Almanca FormatMessage()anlatıldığı gibi
İngilizce Win32Exception almak nasıl?

Bu nedenle, farklı diller için mevcut istisna mesajlarının çoğunu harici dosyalarda saklayan kendi çözümümü oluşturdum. İstediğiniz dilde tam mesajı alamayacaksınız, ancak o dilde, şu anda aldığınızdan çok daha fazla bir mesaj alacaksınız (bu muhtemelen anlamadığınız bir dilde bir mesajdır).

Bu sınıfın statik işlevleri, farklı dillere sahip Windows kurulumlarında yürütülebilir: CreateMessages()kültüre özgü metinler
SaveMessagesToXML()oluşturur, dilleri oluşturulduğu veya yüklendiği kadar çok XML dosyasına kaydeder,
LoadMessagesFromXML()tüm XML dosyalarını dile özgü iletilerle yükler

XML dosyalarını farklı dillere sahip farklı Windows kurulumlarında oluştururken, yakında ihtiyacınız olan tüm dillere sahip olacaksınız.
Birden fazla MUI dil paketi yüklüyse belki 1 Windows'ta farklı diller için metinler oluşturabilirsiniz, ancak henüz test etmedim.

VS2008 ile test edilmiştir, kullanıma hazırdır. Görüş ve önerilerinizi bekliyoruz!

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

1
Thread.CurrentUICulture Ayrıca korkunç bir seçenek haline arayüzünün dilini değiştirir. Klasik bir örnek, mesaj kutusundaki Evet / Hayır / Tamam / İptal düğmeleridir.
Nyerguds

0

İngilizce istisna mesajları

try
{
    ......
}
catch (Exception ex)
{
      throw new UserFriendlyException(L("ExceptionmessagesinEnglish"));
}

ardından Yerelleştirme klasörüne gidin ve projectName.xml dosyasına yerleştirin ve ekleyin

<text name="ExceptionmessagesinEnglish">Exception Message in English</text>

-1

Sadece hata mesajı (IIRC, basit istisna.ToString () bunu sizin için yapmalıdır) yerine çağrı yığınını günlüğe kaydetmelisiniz. Oradan, istisnanın nereden kaynaklandığını tam olarak belirleyebilir ve genellikle hangi istisnanın olduğunu çıkarabilirsiniz.


3
Mesaj ve yığın izlemesini kaydediyoruz. Ancak mesaj açıksa çok daha kolay.
Carra

-1

Uzantı yöntemini kullanarak catch bloğundaki istisna mesajını geçersiz kıl, Atılan iletinin kodda olup olmadığını aşağıda belirtildiği gibi kontrol edin.

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

1
As Daha önce dediğim ... InvalidOperationException. Mesajın kendisi olmadan bunun ne anlama geldiğini anlamak için eğlenin. Yeni bir örnek sihirli bir şekilde sahip olmayacak.
Nyerguds

-1

Günlüğe kaydetme amacıyla, bazı uygulamaların İngilizce özel durum iletisini alması gerekebilir (normal istemcinin UICulture'ta görüntülenmesinin yanı sıra).

Bu amaçla aşağıdaki kod

  1. mevcut UICulture'u değiştirir
  2. "GetType ()" & "Activator.CreateInstance (t)" kullanarak atılan Exception nesnesini yeniden oluşturur
  3. yeni Özel Durum nesnesinin İletisini yeni UICuture'de görüntüler
  4. ve son olarak mevcut UICulture'u eski UICulture'a geri döndürür.

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

1
bu, yeni nesnenin istisna mesajının atılan istisnanınkiyle aynı olduğunu garanti etmez. Tamamen farklı olabilir ve genellikle tamamen farklıdır. Bu yüzden istisna mesajına ihtiyacımız var.
Artemious
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.