我们通过编写Exception来记录系统中发生的任何异常。消息发送到文件。但是,它们是在客户端的文化中编写的。土耳其语的错误对我来说意义不大。
那么,我们如何在不改变用户文化的情况下用英语记录错误消息呢?
我们通过编写Exception来记录系统中发生的任何异常。消息发送到文件。但是,它们是在客户端的文化中编写的。土耳其语的错误对我来说意义不大。
那么,我们如何在不改变用户文化的情况下用英语记录错误消息呢?
当前回答
我可以想象其中一种方法:
异常只会被你读取,也就是说,它们不是客户端特性,所以你可以使用硬连线的非本地化字符串,当你在土耳其模式下运行时不会改变。 每个错误都包含一个错误代码,例如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;
}
您应该记录调用堆栈,而不仅仅是错误消息(IIRC,简单的异常。tostring()应该为您做这件事)。从那里,您可以确定异常的确切来源,并且通常可以推断出它是哪个异常。
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:)
这里有一个解决方案,不需要任何编码,甚至适用于异常的文本加载过早,我们能够通过代码更改(例如,那些在mscorlib)。
它可能并不总是适用于每一种情况(这取决于你的设置,因为你需要能够创建一个。config文件之外的主。exe文件),但这对我来说是可行的。因此,只需在dev中创建一个app.config,(或[myapp].exe。Config或web。Config in production),包含以下行,例如:
<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>
它的作用是告诉框架将mscorlib的资源和System.Xml的资源的程序集绑定重定向到一个程序集,用于版本介于1到999之间的法语(文化设置为“fr”)。不存在(任意版本999)。
因此,当CLR为这两个程序集(mscorlib和System.xml)寻找法语资源时,它不会找到它们,而是优雅地回退到英语。根据上下文和测试,您可能希望将其他程序集添加到这些重定向(包含本地化资源的程序集)。
当然,我认为微软不支持这个功能,所以请自行承担使用风险。好吧,如果您发现了问题,您可以删除这个配置并检查它是否无关。
这个问题可以部分解决。框架异常代码根据当前线程区域设置从其资源加载错误消息。在某些异常的情况下,这将在访问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 cannot be null'部分。在这些情况下,即使在使用上述代码时,消息仍将出现(部分)本地化。
除了使用一些不切实际的技巧,比如在一个带有en-US语言环境的线程上运行所有的非ui代码之外,似乎没有什么可以做的:. net Framework异常代码没有覆盖错误消息语言环境的工具。