我们通过将Exception.Message写入文件来记录系统中发生的任何异常.但是,它们是在客户的文化中写成的.而土耳其的错误对我来说意义不大.
那么如何在不改变用户文化的情况下用英语记录任何错误消息呢?
这个问题可以部分解决.Framework异常代码根据当前线程区域设置从其资源加载错误消息.在某些例外情况下,这会在访问Message属性时发生.
对于这些例外情况,您可以通过在记录时将线程区域设置简单地切换到en-US来获取完整的美国英语版本的消息(事先保存原始用户区域设置并在之后立即恢复).
在单独的线程上执行此操作甚至更好:这可确保不会产生任何副作用.例如:
try { System.IO.StreamReader sr=new System.IO.StreamReader(@"c:\does-not-exist"); } catch(Exception ex) { Console.WriteLine(ex.ToString()); //Will display localized message ExceptionLogger el = new ExceptionLogger(ex); System.Threading.Thread t = new System.Threading.Thread(el.DoLog); t.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); t.Start(); }
ExceptionLogger类看起来像:
class ExceptionLogger { Exception _ex; public ExceptionLogger(Exception ex) { _ex = ex; } public void DoLog() { Console.WriteLine(_ex.ToString()); //Will display en-US message } }
但是,正如Joe在对此回复的早期修订版的评论中正确指出的那样,在抛出异常时已经(部分)从语言资源加载了一些消息.
例如,这适用于抛出ArgumentNullException("foo")异常时生成的消息的'parameter not not null'部分.在这些情况下,即使使用上述代码,消息仍将显示(部分)本地化.
除了使用不切实际的黑客之外,例如在开始使用en-US语言环境的线程上运行所有非UI代码,似乎没有太多可以做的事情:.NET Framework异常代码没有用于覆盖错误消息区域设置的工具.
您可以在unlocalize.com上搜索原始异常消息
也许是一个有争议的观点,但en-US
您可以将其设置为,而不是将文化设置为Invariant
.在Invariant
文化中,错误消息是英文的.
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
它具有不偏见的优点,特别是对于非美国英语区域.(又避免同事的讽刺言论)
Windows需要安装要使用的UI语言.它没有,它无法神奇地知道翻译的消息是什么.
在en-US windows 7 ultimate中,安装了pt-PT,代码如下:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("pt-PT"); string msg1 = new DirectoryNotFoundException().Message; Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); string msg2 = new FileNotFoundException().Message; Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR"); string msg3 = new FileNotFoundException().Message;
在pt-PT,en-US和en-US中生成消息.由于没有安装法语文化文件,因此默认使用Windows默认(已安装?)语言.
这里的解决方案不需要任何编码,甚至可以用于过早加载的异常文本,以便我们能够通过代码进行更改(例如,mscorlib中的那些).
它可能并不总是适用于所有情况(这取决于您的设置,因为您需要能够在主.exe文件旁边创建.config文件)但这对我有用.因此,只需创建一个包含以下行的app.config
dev,(或一个[myapp].exe.config
或web.config
在生产中),例如:
... ...
这样做是告诉框架重定向程序集绑定mscorlib
的资源和System.Xml
资源,对于1到999之间的版本,法语(culture设置为" fr
")到一个不存在的程序集(任意一个)版本999).
因此,当CLR为这两个程序集(mscorlib和System.xml)查找法语资源时,它将无法找到它们并优雅地回退到英语.根据您的上下文和测试,您可能希望将其他程序集添加到这些重定向(包含本地化资源的程序集).
当然我不认为这是微软支持的,所以使用风险自负.好吧,如果您发现问题,您可以删除此配置并检查它是否无关.