GetUserDefaultLCID in .NET with no API calls

13. September 2012 09:43 by Mrojas in C#, Portable  //  Tags: , ,   //   Comments (0)

I was looking for a pure .NET equivalent of the Windows API function

GetUserDefaultLCID because I want my code to be free of pinvoke references

to avoid posible issues in 64 bits.

 

However after a lot of digging I found that there is not direct equivalent.

You could use Thread.CurrentThread.CurrentCulture.LCID but it is not exactly the same.

So I found this great post in stackoverflow:

 

 

"

For some background information have a look here:

 

http://blogs.msdn.com/b/michkap/archive/2010/03/19/9980203.aspx

 

So it seems this problem manifests itself on Vista as well as Windows 7. It occurs because Microsoft seems to be in the process of deprecating the Locale ID in favor of the Locale Name.

 

To summarize: The relevant API calls all operate on registry values that can be found at HKCU\Control Panel\International. The value "Locale" is maintained for backward compatibility reasons and under normal circumstances is kept in synch with its newer counterpart called "LocaleName". This synch process however doesn't work under some circumstances.

 

Anyway, the GetThreadLocale API call gets its return value from the "Locale" registry entry mentioned above, while the others (GetUserDefaultLCID, GetSystemDefaultLCID, etc) use the "LocaleName" registry entry.

 

Hence the confusion.

 

BTW, the solution mentioned by JP in a previous post should probably be extended to

 

initialization

  SetThreadLocale(GetUserDefaultLCID);

  GetFormatSettings;

because (if i'm reading it correctly!) according to the docco the GetUserDefaultLCID call will account for user customizations.

 

After a bit more research, Vista is not affected at all. I've got some more detail too ...

 

The relevant API calls all operate on registry values that can be found at HKCU\Control Panel\International. The value " Locale " is maintained for backward compatibility reasons and under normal circumstances is kept in synch with its newer counterpart called " LocaleName ". Under Windows 7 at least, this synch process however doesn't work where processes are being run as another user (i.e. RunAs or Impersonation). This seems to be the case during installation, where the installer is launched from an existing windows session. It does however seem to work correctly if you've booted from the install CD.

 

GetThreadLocale gets its value from Thread Information Block or Thread Environment Block (TIB or TEB) See: http://en.wikipedia.org/wiki/Thread_Environment_Block For both Vista and Windows 7, the TIB is initialised with the HKCU\Control Panel\International\Locale registry entry at logon. This becomes the default Locale for all threads created during the session. Changing this registry value during a session has no effect on the value returned by the GetThreadLocale API call. The user must log out and log in again to see a change. This is the API call that Delphi uses as the basis to initialize all its locale format strings ( See SysUtils.GetFormatSettings method), from which all date fields are formatted.

 

GetUserDefaultLCID: in Vista, bases its return value on the HKCU\Control Panel\International\Locale registry entry. In Windows 7, bases its return value on the HKCU\Control Panel\International\LocaleName registry entry. The respective registry entry can be changed during a session and the result is immediately reflected in this API call return value.

 

SetThreadLocale updates the TIB to reflect the locale provided in the parameter to this call. Note that this only ever effects the thread the API call is executed from. The API calls SetThreadLocale(LOCALE_USER_DEFAULT) and SetThreadLocale(GetUserDefaultLCID) are functionally equivalent. They both derive the source locale as described in the GetUserDefaultLCID API call above."

 

With that information you could create a function to get that value from the Registry using just .NET framework calls. I do not love that approach either but at least is another alternative