我们通过将Exception.Message写入文件来记录系统中发生的所有异常。但是,它们是按照客户的文化来编写的。土耳其语的错误对我来说意义不大。
那么,如何在不改变用户文化的情况下用英语记录错误消息呢?
我们通过将Exception.Message写入文件来记录系统中发生的所有异常。但是,它们是按照客户的文化来编写的。土耳其语的错误对我来说意义不大。
那么,如何在不改变用户文化的情况下用英语记录错误消息呢?
Answers:
此问题可以部分解决。框架异常代码根据当前线程语言环境从其资源加载错误消息。在某些情况下,这是在访问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”)异常时生成的消息的“参数不能为null”部分。在这些情况下,即使使用上面的代码,消息仍将(部分)本地化。
除了通过使用不切实际的技巧(例如,在以en-US语言环境开始的线程上运行所有非UI代码)之外,您似乎无能为力:.NET Framework异常代码没有覆盖错误消息语言环境的工具。
t.CurrentUICulture = new System.Globalization.CultureInfo("fr-FR");
,t.CurrentCulture = new System.Globalization.CultureInfo("fr-FR");
但是,最终的例外情况是英语...
Environment.GetResourceString("...")
因此您的解决方案不再起作用。最好的办法是使用您自己的(英语)消息文本引发自定义异常,并使用InnerException属性保留旧的异常。
您可以在unlocalize.com上搜索原始异常消息。
No records found
。
也许这是一个有争议的观点,但是en-US
您可以将其设置为,而不是将文化设置为Invariant
。在Invariant
文化中,错误消息是英文的。
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
它具有不显得偏见的优点,尤其是对于非美国英语地区。(也避免了同事的sn亵言论)
catch
。
这是一种不需要任何编码的解决方案,甚至可以处理异常文本,因为这些文本加载得太早,以至于我们无法通过代码进行更改(例如,mscorlib中的异常)。
它可能并不总是适用于每种情况(它取决于您的设置,因为您需要能够在主.exe文件旁边创建一个.config文件),但它对我有用。因此,只需创建一个包含以下几行的app.config
in dev(或a [myapp].exe.config
或web.config
生产中):
<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>
这是告诉框架将法语资源(介于1和999之间的版本)的mscorlib
's资源和System.Xml
's资源的程序集绑定重定向fr
到...不存在的程序集(任意999版)。
因此,当CLR为这两个程序集(mscorlib和System.xml)寻找法语资源时,它将找不到它们并优雅地回退为英语。根据您的上下文和测试,您可能想要向这些重定向添加其他程序集(包含本地化资源的程序集)。
当然,我认为这不受Microsoft支持,因此使用时后果自负。好吧,如果您发现问题,则可以删除此配置并检查它是否无关。
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默认(已安装?)语言。
我知道这是一个老话题,但是我认为我的解决方案可能与在网络搜索中偶然发现它的任何人有关:
在异常记录器中,您可以记录ex.GetType.ToString,这将保存异常类的名称。我希望类的名称应独立于语言,因此始终以英语表示(例如“ System.FileNotFoundException”),尽管目前我无法访问外语系统来测试理念。
如果您也确实想要错误消息文本,则可以使用您喜欢的任何一种语言创建一个词典,其中包含所有可能的异常类名称及其等效消息,但是对于英语,我认为该类名称已足够。
InvalidOperationException
扔了System.Xml.XmlWellFormedWriter
。您尝试猜测发生了什么特定错误,而不阅读消息。可能是一千种不同的东西。
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 :)
设置Thread.CurrentThread.CurrentUICulture
将用于本地化异常。如果您需要两种异常(一种针对用户,一种针对您),则可以使用以下函数来转换异常消息。它在.NET-Libraries资源中搜索原始文本,以获取资源密钥,然后返回转换后的值。但是有一个缺点,我还没有找到一个好的解决方案:找不到资源中包含{0}的消息。如果有人有一个好的解决方案,我将不胜感激。
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)
}
.NET框架分为两个部分:
.NET框架本身中的所有文本(例如,异常消息,MessageBox上的按钮标签等)都是英语。语言包具有本地化的文本。
根据您的实际情况,一种解决方案是卸载语言包(即告诉客户端这样做)。在这种情况下,例外文本将为英文。但是请注意,所有其他框架提供的文本也将是英语(例如,MessageBox上的按钮标签,ApplicationCommands的键盘快捷键)。
我可以想象其中一种方法:
异常仅由您读取,即它们不是客户端功能,因此您可以使用在土耳其语模式下运行时不会更改的硬连线非本地化字符串。
包括一个错误代码,例如0x00000001
每个错误,以便您可以轻松地在英语表中查找它。
基于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;
}
我遇到过同样的情况,在这里和其他地方找到的所有答案都没有帮助或不满意:
在Thread.CurrentUICulture
改变了.NET异常的语言,但它并不适用于Win32Exception
,它使用Windows资源在Windows UI本身的语言。因此,我从未设法Win32Exception
用英语而不是德语来打印消息,甚至没有FormatMessage()
按照如何获取英语中的Win32Exception中所述使用消息进行打印
。
因此,我创建了自己的解决方案,该解决方案将大多数不同语言的现有异常消息存储在外部文件中。您不会以所需的语言得到非常准确的消息,但是会以该语言得到一条消息,该消息比您当前所获得的消息要多得多(这是您可能不理解的语言的消息)。
此类的静态功能可以在Windows安装中使用不同的语言来执行:
CreateMessages()
创建特定于文化的文本,
SaveMessagesToXML()
将其保存到创建语言或加载
LoadMessagesFromXML()
时所保存的XML文件中,并加载所有具有特定于语言的消息的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");
}
}
Thread.CurrentUICulture
也改变了用户界面的语言,使其成为一个可怕的选择。一个经典的例子是消息框中的是/否/确定/取消按钮。
英文异常消息
try
{
......
}
catch (Exception ex)
{
throw new UserFriendlyException(L("ExceptionmessagesinEnglish"));
}
然后转到本地化文件夹并将其放置在projectName.xml中并添加
<text name="ExceptionmessagesinEnglish">Exception Message in English</text>
您应该记录调用堆栈,而不仅仅是错误消息(IIRC,简单的exception.ToString()应该为您完成此操作)。从那里,您可以准确确定异常的来源,通常可以推断出异常是什么。
使用扩展方法覆盖catch块中的异常消息,如下所述,检查抛出的消息是否来自代码。
public static string GetEnglishMessageAndStackTrace(this Exception ex)
{
CultureInfo currentCulture = Thread.CurrentThread.CurrentUICulture;
try
{
dynamic exceptionInstanceLocal = System.Activator.CreateInstance(ex.GetType());
string str;
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
if (ex.Message == exceptionInstanceLocal.Message)
{
dynamic exceptionInstanceENG = System.Activator.CreateInstance(ex.GetType());
str = exceptionInstanceENG.ToString() + ex.StackTrace;
}
else
{
str = ex.ToString();
}
Thread.CurrentThread.CurrentUICulture = currentCulture;
return str;
}
catch (Exception)
{
Thread.CurrentThread.CurrentUICulture = currentCulture;
return ex.ToString();
}
InvalidOperationException
。弄清楚没有消息本身的含义,这很有趣。一个新实例不会神奇地拥有它。
为了进行日志记录,某些应用程序可能需要获取英语异常消息(除了在常规客户端的UICulture中显示之外)。
为此,下面的代码
然后最后将当前的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();
}