views:

4698

answers:

8

We are logging any exceptions that happen in our system by writing the Exception.Message to a file. However, they are written in the culture of the client. And Turkish errors don't mean a lot to me.

So how can we log any error messages in English without changing the users culture?

+4  A: 

I would imagine one of these approaches:

1) The exceptions are only ever read by you, i.e. they are not a client feature, so you can use hardwired non localised strings that won't change when you run in turkish mode.

2) Include an error code eg. 0X00000001 with each error so that you can easily look it in up in an english table.

morechilli
+13  A: 

This issue can be partially worked around. The Framework exception code loads the error messages from its resources, based on the current thread locale. In the case of some exceptions, this happens at the time the Message property is accessed.

For those exceptions, you can obtain the full US English version of the message by briefly switching the thread locale to en-US while logging it (saving the original user locale beforehand and restoring it immediately afterwards).

Doing this on a separate thread is even better: this ensures there won't be any side effects. For example:

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

Where the ExceptionLogger class looks something like:

class ExceptionLogger
{
  Exception _ex;

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

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

However, as Joe correctly points out in a comment on an earlier revision of this reply, some messages are already (partially) loaded from the language resources at the time the exception is thrown.

This applies to the 'parameter cannot be null' part of the message generated when an ArgumentNullException("foo") exception is thrown, for example. In those cases, the message will still appear (partially) localized, even when using the above code.

Other than by using impractical hacks, such as running all your non-UI code on a thread with en-US locale to begin with, there doesn't seem to be much you can do about that: the .NET Framework exception code has no facilities for overriding the error message locale.

mdb
Your example works for a FileNotFoundException, because the message resource is retrieved when the Message property is accessed, not when the exception is thrown. But this is not true for all exceptions (e.g. try throw new ArgumentNullException("paramName"))
Joe
+1  A: 

Along these lines, I still am not comfortable with the design of errors in .net. It's exception classes and events, with text descriptions. You discover the error based on the exception class thrown, and the text description of the error. There are usually no numeric error codes (unless they are buried within an inner system exception) that you can look up in a well defined list of errors. Why wouldn't that be simpler?

P a u l
+2  A: 
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;

Without WORKAROUNDS.

Tks :)

This appears to be the same workaround as mdb?
Martin
+1  A: 

Apparently, attempting to change the thread culture will only get you so far. I've been trying to debug an issue on a Russian version of Windows, and cannot get any .Net exceptions to appear in English.

JoelHess
A: 

In my program I read the local I want my program to run in by setting the "Thread.CurrentThread.CurrentUICulture" at start-up. This is used to correctly load and display the translated messages.

However, on my develolment machine (en.US) the exception messages are always in English so there must be something other than CurrentUICulture controlling the translation of the exception messages...

Trevor Beacon
A: 

You should log the call stack instead of just error message (IIRC, simple exception.ToString() should do that for you). From there, you can determine exactly where the exception originated from, and usually deduce which exception it is.

Branko Dimitrijevic
We're logging the message and stacktrace. But it's a lot easier if the message is clear.
Carra
+3  A: 

You can search for the original exception message at unlocalize.com