Getting the real (localized) name of the keyboard

by Michael S. Kaplan, published on 2006/05/06 03:01 -04:00, original URI:

The other day, someone had asked Dr. International about how to get the names of all the keyboards, the ones that appear in the Language Bar.

Now this is definitely not the easiest thing in the world, so I figured I ought to show the best way to do it....

The key is to look under the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\

Each subkey represents a KLID (Keyboard Layout Identifer) for a specific keyboard layout.

Under each of these keys you will see some of the following values:

Now obviously for the current question, only the Layout Text and Layout Display Name are relevant (the latter for XP and later, the former for prior versions and to act as a fallback).

So the code can be something simple, like the following:

        [DllImport("shlwapi.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
        internal static extern uint SHLoadIndirectString(string pszSource,
            StringBuilder pszOutBuf,
            uint cchOutBuf,
            IntPtr ppvReserved);

        internal static void KeyboardsOnMachine()
            Microsoft.Win32.RegistryKey rk = null;
            Microsoft.Win32.RegistryKey rkSub = null;

            try {
                rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts");
                if(null == rk) {
                    Console.WriteLine("Registry corrupt.");
                    throw(new System.Security.SecurityException());

                foreach(string stSubKey in rk.GetSubKeyNames()) {
                    rkSub = rk.OpenSubKey(stSubKey, false);

                    if(null == rkSub) {
                        Console.WriteLine("Registry corrupt.");
                        throw(new System.Security.SecurityException());
                    string stLayoutName = "";
                    string stLayoutText = rkSub.GetValue("Layout Text", "").ToString();
                    string stDisplayNameString = rkSub.GetValue("Layout Display Name", "").ToString();

                    if(null != stDisplayNameString &&
                        stDisplayNameString.Length  > 0) {
                        StringBuilder sbName = new StringBuilder(260);

                        if(0 == SHLoadIndirectString(
                            stDisplayNameString, sbName, (uint)sbName.Capacity, IntPtr.Zero)) {
                            stLayoutName = sbName.ToString();

                    if(stLayoutName.Length == 0) {
                        stLayoutName = stLayoutText;

                    if(stLayoutName.Length > 0) {

            catch(System.Security.SecurityException) { }
            catch(ArgumentException) { }
            finally {
                if(null != rkSub) {
                if(null != rk) {


This code will build a nice big list of all of the available keyboards on the machine....


This post brought to you by "ಎ" (U+0c8e, a.k.a. KANNADA LETTER E)

# Jochen Kalmbach on 6 May 2006 2:26 PM:

An other interesting question (at least for me): How can I set the Keyboard and UI-Language on a MUI system via a program? We need this for an "automatic" post-install of the computer...
I couldn´t find any API to change the UI and keyboard layout permanently (OS default).

# Michael S. Kaplan on 6 May 2006 3:48 PM:

Hello Jochen --

The UI language is a user-configurable setting -- why would you want to be changing the user's UI language?

# Jochen Kalmbach on 6 May 2006 4:28 PM:

Hi Michael!
I need to change the UI language (and keyboard) as a "post-install" of our software on WinXP-Embedded due to customer specs.
Currently we nned to manually open the Control Panel and change it... isn´t there any simpler way (API), so I can automatically do this?

# Michael S. Kaplan on 6 May 2006 5:08 PM:

Hi Jochen,

Well, there is no Win32 API function to support it no. However, both SysPrep and the unattend features of intl.cpl (which I have discussed previously) should allow it to be set.

# Jochen Kalmbach on 8 May 2006 7:11 AM:

Hi Michael!

Thank you very much! You directed me to the correct KB-article (! It seems that I missed this post...


referenced by

2008/05/11 The vector of this spam is [apparently] indeterminate

2008/04/09 Fight the Future? (#11 of ??), aka Microsoft is giving this character nada weight but lotsa importance

2008/03/06 Getting the IME name (for someone who speaks Chinese, based on code from an article written in Chinese, when you don't speak Chinese)

2007/10/31 Making things better out from under people: the story of MUI

2007/10/19 A less intelligent strain of blog spam

2007/01/05 How can be changed the keyboard layout name label?

2006/05/06 Keyboards and time zones have something in common

go to newer or older post, or back to index or month or day