by Michael S. Kaplan, published on 2006/05/06 03:01 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2006/05/06/591174.aspx
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) {
Console.WriteLine("{0}\t{1}",
stSubKey,
stLayoutName);
}
rkSub.Close();
}
}
catch(System.Security.SecurityException) { }
catch(ArgumentException) { }
finally {
if(null != rkSub) {
rkSub.Close();
}
if(null != rk) {
rk.Close();
}
}
return;
}
}
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:
# Michael S. Kaplan on 6 May 2006 3:48 PM:
# Jochen Kalmbach on 6 May 2006 4:28 PM:
# Michael S. Kaplan on 6 May 2006 5:08 PM:
# Jochen Kalmbach on 8 May 2006 7:11 AM:
referenced by
2008/05/11 The vector of this spam is [apparently] indeterminate
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