How does a .NET process get the culture information? - c#

I have a Windows service running (C#, .NET 2.0) on Windows Server 2003 R2. In one server the System.Threading.Thread.CurrentThread.CurrentCulture is {en-AU} and in the other {en-US}.
This has caused a difference when calling ToString() on a DateTime object. I want the culture to be {en-AU}.
I checked the "Regional and Language Setting". In both servers, the "Regional Options" tab shows "English (Asutralia)". But in the "Advanced" tab it shows "English (United States)" for one and "English (Australia)" for the other. So this must be causing the difference. Although I want to know why exactly the "Advanced" tab says "the language version of the non-unicode programs you want to use", I thought .NET processes were Unicode and should not be affected by this.
How does the .NET runtime determine the culture to use? Any detailed reference would be helpful.

If a culture has not been set on the thread, Thread.CurrentThread.CurrentCulture defaults to the "user default culture" - which it gets from the underlying OS. This is determined by the Formats section in the regional control panel applet.
For a service, it has no control panel settings by default like for a user (the case above) as it runs under the LocalSystem account which will not have a profile, so it uses the system locale from the OS. I'm not sure if this can be set for a service by adjusting the settings in Windows.
There are a few things you could do:
you can explicitly set the CurrentCulture of the main thread when the service starts. If you do this, you will need to bear in mind that any new threads that are created in your service will also need to have their CurrentCulture set as well, as threads do not inherit their culture from parent threads.
you can set the service to run as a specific user, and set that user's regional settings (the formats section) to be the culture you want to use. When the service starts as that use,it will use that user's regional settings.
since your problem seems to be related to calling DateTime.ToString(), make sure you pass the AU culture to the ToString() method:
DateTime.ToString(new CultureInfo("en-AU"))
You could add this as an extension method to save you having to do this everywhere:
public static string ToAUString(this DateTime dateTime)
{
return dateTime.ToString(new CultureInfo("en-AU"));
}
You can then call DateTime.ToAUString() to get the correct output.

In my case it took only one line of code to change the Culture:
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo( "en-US" )
It changes default Culture of Main thread and new ones as well.

This MSDN page on CultureInfo has some information that might be relevant:
The user might choose to override some of the values associated with the current culture of Windows through the regional and language options portion of Control Panel. For example, the user might choose to display the date in a different format or to use a currency other than the default for the culture. In general, your applications should honor these user overrides.
If UseUserOverride is true and the specified culture matches the current culture of Windows, the CultureInfo uses those overrides, including user settings for the properties of the DateTimeFormatInfo instance returned by the DateTimeFormat property, and the properties of the NumberFormatInfo instance returned by the NumberFormat property. If the user settings are incompatible with the culture associated with the CultureInfo, for example, if the selected calendar is not one of the OptionalCalendars, the results of the methods and the values of the properties are undefined.
I think this might be a good starting point for your investigations.

Related

HttpContext.Current.Request.UserLanguages is NULL when first loading IE11/Edge in European countries

I support an application (c#/asp.net) that uses multiple languages using .Resx files for numerous European countries. Recently, some users upgraded to Windows 10 and thus Internet Explorer 11. Now when they load the application, it defaults the main page to en-US and when they go to a page that calls a function that references HttpContext.Current.Request.UserLanguages[0], it comes back as NULL, thus causing a crash with a NULL reference error.
If they change their language settings in any way (add, remove or move a language up or down), then HttpContext.Current.Request.UserLanguages[0] is populated with that top language. However, once they reboot their machine and re-open IE11, then the field is NULL again until they change their settings yet again.
How can I set/detect the correct language without having the user to change their language settings every time they open IE11 after a reboot?
This error does not happen in Chrome, but some users may not have access to Chrome.
Notes I have discovered from past research and are currently in my project:
All pages have Culture="auto" and UICulture="auto";
When first loading the application, System.Threading.Thread.CurrentThread.CurrentUICulture = en-US (and not their default language); (same goes for CurrentCulture as well - both are initially set to en-US)
After they change their language settings, then System.Threading.Thread.CurrentThread.CurrentUICulture changes to be their set language (e.g.: fr-CH for French Swiss);
To summarize: How do I detect IE11's language setting for the user when Request.UserLanguages is NULL and when the CurrentThread.CurrentUICulture is defaulting to en-US and not their system's language? Is there a workaround for using Request.UserLanguages?
I had a user go into Edge and try it out and the same problems occur. The application is not picking up the local culture/language - it is defaults to en-US and not en-UK or fr-CH for example. Also, the application is coded to check different cultures to display dates in the format of the culture, so for Europe, the DD/MM/YYYY format is needed and US - MM/DD/YYYY; currency is also different. So I need to be able to detect the correct culture in Windows 10 without having the user change their language settings to set HttpContext.Current.

Inconsistent DecimalSeparator value

When I apply toString() on a number of type double, I get the string with . as the decimal separator. In one of my projects only, I get , as the decimal separator.
I have not changed CultureInfo data. My CurrentCulture is el-GR in all my projects which is the default system Culture. el-GR uses , as the decimal separator but I have changed this value through Windows Regional Settings to . which is reflected correctly to all my projects except the one in question.
The only difference I can tell is that it is a Web Site and not a usual Visual Studio Project. I do not know if this forces Visual Studio NOT to take into account the local computer NumberFormat exceptions and if/how this can be changed.
The CultureInfo your program use, if you don't explicitly set it somehow in code, is related to Regional Settings of current user.
When running a web project, very likely current user is not you, the one logged in in the computer, but a built-in user IIS uses. see this question and display somehow current user to find out if your problem is actually related to this.
To change regional settings for your (.Net & IIS hosted) web application, you can use different method: web.config of your application, web.config of the whole server, settings for IIS, or even tweak the registry.
Have a look at this thread (and also linked threads you find in the left column) for methods you can use.

CultureInfo("fr-BE") different on Windows 8.1 than before

I set the culture for an .NET web app in order to use specific format for numbers, currency and date:
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-BE");
On an Windows 2008 server machine with IIS 7 I get "d/m/yy" as short date format (what I want).
On my (new) Windows 8.1 pro machine (developer and test) I get "d-m-yy" format for the same CultureInfo..."dash" instead of "slash" separator.
I've checked also in Control Panel -> Region and the settings for French(Belgium) are as mentioned above, different in W2k8 server than in W8.1pro...
The .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8... Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat; if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
Does anybody knows about it? Belgium changed national standards? Or, Microsoft did for them? Any idea?
Thanks.
Thanks for the answers. .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8...
Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat;
if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
I was looking at similar issue for CultureInfo 'en-NZ', as it been changed for the same culture setting in different Windows version, and cause my web service saved different strings for the same CultureInfo, and it turns out it is provided by Windows since .Net Framework 4, and was a combination of Windows and .Net before that.
Lucky for me, I can make use of Invariant culture, which was recommended by Microsoft to make sure the string I saved into Database not going to be changed because of Windows or future .Net Framework update. The thing is, for my case it was the AM\PMDesignator changed from a.m.\p.m. to AM\PM, and the Invariant culture will make sure it saves to AM\PM I assume it will not change in the future, but if I want it save to a.m.\p.m. as it was for older version of Windows, Invariant culture wouldn't be able to do that, I will probably need define my own custom culture or overwrite the current culture as you did.
See the other question about Microsoft specified that CultureInof are subject to change without notice

Regarding windows form localization C# [duplicate]

This question already has answers here:
What is the difference between CurrentCulture and CurrentUICulture properties of CultureInfo in .NET?
(5 answers)
Closed 8 years ago.
I have noticed people use this code to localize
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Could anyone tell me what CurrentUICulture and CurrentCulture are? Why do we need to assign same value to both
What will happen if I assign the value CultureInfo("fr-FR"); to only CurrentUICulture or CurrentCulture?
I would really like to know in detail what CurrentUICulture and CurrentCulture does?
Suppose client pc language setting could be German or French etc., but I want to develop my application in such a way that whatever language setting is there, my apps will work in that pc with their language setting. I mean that all the controls will show the text in German or French. I do not want to hard code the culture this way CultureInfo("fr-FR")
I would rather the user's language setting dictate the language of my controls. How would I go about doing this?
It's pretty simple.
CurrentCulture is the culture assigned for thread to be used in various culture-specific methods. To example, ToString() one.
CurrentUICulture is
used by the Resource Manager to look up culture-specific resources at run time.
By setting both you ensure what all ToString() works correctly and your form resources are loaded from appropriate satellite.
Regarding usage, you may think to provide user with option to change language. To example, I have native German windows, but I set English culture in it (date format and default culture for console applications), while I speak Russian. Which language do you think I will chose when using your software? =P
By default, either take language chosen in installer (if you have installer in multiple languages and options to change it there) or current Windows user language preferences.
One possible scenario:
Preconditions: application is already localized, satellites are there (if not, read this). I don't like satellites myself, but they are easy to start with.
When application starts, you create a list of available languages (either statically or by enumerating satellites).
string[] Languages = new[] {"en", "fr", "de", "ru"};
Then, if application start for the first time (to example, you have string language setting and it's by default null or "", this would be a flag what no language is selected yet), you detect default os language
var language = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName; // to ex, "fr"
and if it's in your list, then you set
Thread.CurrentThread.CurrentUICulture =
Thread.CurrentThread.CurrentCulture = new new CultureInfo(language);
Otherwise, if you don't have this language, then use "default" language (to example, "en"). If its done at at the start of your application, then any further constructed and used window will use proper resources.
User should be able to change language. Give him possibility to chose one of available Languages. In winforms you will have to reload forms after change culture. Easiest solution would be to simply tell user what "software restart is required".

How can I change a Windows user's regional settings/date format?

I use a VB6/COM+ application which outputs date/time values based on the short date settings in the Control Panel, Regional Settings, for the user that runs it. The program that then parses that output has a configurable setting for the date format it expects, and presents in the UI.
e.g. If the regional setting for the user is set to mm/dd/yyyy, and it outputs 06/18/2009, the application expecting "18/06/2009" fails with "String was not recognized as a valid DateTime".
As we usually run this application as a service account, which we have not logged in as interactively to create a profile, we generally set the correct date format and then tick the "Apply all settings to the current user account and the default user profile" option.
I would like to be make the C# configuration utility I have written for this mess to be able to set the date format programmatically for a given user.
Edit
I would like nothing more than to change the code, but do not have the ability to do so at this time.
I also know that what I am asking is a bad thing to do. With regards to "it should be the user's choice" - I am that user, as I create it explicitly for the task; I just want to set the date format by a scripted method, rather than having to do the clicking myself.
This is specifically discouraged by Microsoft. Any solution you may come up with will be a filthy hack that will probably stop working soon.
Think of it this way: who are you to decide those settings? Don't you think that's the user's decision?
Back on topic: find an unambiguous format for the applications to communicate in, such as YYYYMMDD. The application that displays can then simply respect the actual user settings, as it should.
But, since you can't change it, just poke into the registry:
Current user:
HKEY_CURRENT_USER\Control Panel\International
Specific user:
HKEY_USERS\(user SID)\Control Panel\International
Default user:
HKEY_USERS\.DEFAULT\Control Panel\International
sShortDate is probably the value you want to change.
If you are going to modify the profile to suit your needs, why not just ignore the profile settings and hardcode the format you want in your app?
code:
Imports System.Threading
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US", False)
Microsoft.Win32.Registry.SetValue("HKEY_CURRENT_USER\Control Panel\International", "sShortDate", "M/d/yyyy")
While persistently changing a user's culture (regional settings) is to be done cautiously, there are legitimate use cases.
On Windows 8 and Windows Server 2012 and above, Windows PowerShell comes with the
Set-Culture cmdlet, which is the programmatic equivalent of choosing a different region via Control Panel (intl.cpl).
For instance, Set-Culture fr-CA is the equivalent of interactively choosing region French (Canada) for the current user.
Caveat: Mixed cultures such as en-DE (sic) appear not to work as of Windows PowerShell v5.1 - see this answer of mine.
While it won't be fast, it is possible to call PowerShell commands from C#.

Categories

Resources