Программирование КПК и смартфонов на .NET Compact Framework.
Реестр.
Реестр является важной частью любой операционной системы семейства Windows. Не является исключением и система Windows Mobile, в которой тоже имеется собственный реестр. Однако разработчики компании Microsoft не стали включать редактор реестра в состав Windows Mobile. Поэтому для доступа к разделам реестра приходится устанавливать программы от сторонних производителей.
Однако любой программист может написать свой редактор реестра, используя возможности .NET Compact Framework. При этом следует учитывать, что в библиотеке .NET Compact Framework 2.0 появились классы для работы с разделами реестра. Если же вы продолжаете писать программы с использованием .NET Compact Framework 1.0, то придется вызывать функции Windows API.
В листинге 13.17 приведен код, который будет работать в любой версии .NET Compact Framework.
Листинг 13.17.
Using System;
Using System.Collections.Generic;
Using System.Text;
Using System.Runtime.InteropServices;
Namespace Registry_CS {
class Registry {
/// <summary>
/// Создает ключ.
/// </summary>
/// <param name="кеуNаmе">Имя создаваемого ключа</раrаm>
/// <returns>B успешном случае возвращается.
/// ERROR_SUCCESS</ returns>
public static int CreateKey(UIntPtr root, string keyName) {
UIntPtr hkey = UintPtr.Zero;
uint disposition = 0;
try {
return.
RegCreateKeyEx(root, keyName, 0, null, 0, KeyAccess.None, IntPtr.Zero,
ref hkey, ref disposition);
} finally {
if (UIntPtr.Zero != hkey) {
RegCloseKey(hkey);
}
}
}
/// <summary>
/// Удаляет ключ.
/// </summary>
/// <param name="кеуNаmе">Имя ключа</раrаm>
/// <returns>B успешном случае возвращается.
/// ERROR_SUCCESS</returns>
public static int DeleteKey(UIntPtr root, string keyName) {
return RegDeleteKey(root, keyName);
}
/// <summary>
/// Создает строковой параметр в заданном ключе.
/// </summary>
/// <param name="кеуNаmе">Имя ключа</раrаm>
/// <param name="vаluеNаmе">Имя параметра</раrаm>
/// <param name="stringDаtа">Значение параметра</раrаm>
/// <rеturns>В успешном случае возвращается.
/// ERROR_SUCCESS</returns>
public static int CreateValueString(string keyName, string valueName,
string stringData) {
UIntPtr hkey = UintPtr.Zero;
try {
int result = RegOpenKeyEx(root, keyName, 0, KeyAccess.None, ref hkey);
if (ERROR_SUCCESS != result) return result;
byte[] bytes = Encoding.Unicode.GetBytes(stringData);
return RegSetValueEx(hkey, valueName, 0, KeyType.String, bytes,
(uint)bytes.Length);
} finally {
if (UIntPtr.Zero != hkey) {
RegCloseKey(hkey);
}
}
}
/// <summary>
/// Создает параметр типа DWORD в заданном ключе.
/// </summary>
/// <param name="кеуNаmе">Имя ключа</раrаm>
/// <param name="vаluеNаmе">Имя параметра</раrаm>
/// <param name="dwоrdDаtа">Значение параметра</раrаm>
/// <rеturns>В успешном случае возвращается.
/// ERROR_SUCCESS</returns>
public static int CreateValueDWORD(UIntPtr root, string keyName,
string valueName, uint dwordData) {
UIntPtr hkey = UintPtr.Zero;
try {
int result = RegOpenKeyEx(root, keyName, 0, KeyAccess.None, ref hkey);
if (ERROR_SUCCESS != result) return result;
byte[] bytes = BitConverter.GetBytes(dwordData);
return RegSetValueEx(hkey, valueName, 0, KeyType.Dword, bytes,
(uint)bytes.Length);
} finally {
if (UIntPtr.Zero != hkey) {
RegCloseKey(hkey);
}
}
}
/// <summary>
/// Создает двоичный параметр в заданном ключе.
/// </summary>
/// <param name="кеуNаmе">Имя ключа</раrаm>
/// <param name="vаluеNаmе">Имя параметра</раrаm>
/// <param name="dwоrdDаtа">Значение параметра</раrаm>
/// <returns>B успешном случае возвращается.
/// ERROR_SUCCESS</returns>
public static int CreateValueBinary(UIntPtr root, string keyName,
string valueName, uint binData) {
UIntPtr hkey = UintPtr.Zero;
try {
int result = RegOpenKeyEx(root, keyName, 0, KeyAccess.None, ref hkey);
if (ERROR_SUCCESS != result) return result;
byte[] data = BitConverter.GetBytes(binData);
return RegSetValueEx(hkey, valueName, 0, KeyType.Binary, data,
(uint)data.Length);
} finally {
if (UIntPtr.Zero != hkey) {
RegCloseKey(hkey);
}
}
}
/// <summary>
/// Получает значение строкового параметра.
/// </summary>
/// <param name="кеуNаmе">Имя ключа</раrаm>
/// <param name="vаluеNаmе">Имя параметра</раrаm>
/// <param name="stringRеsult">строковые данные</раrаm>
/// <rеturns>В успешном случае возвращается.
/// ERROR_SUCCESS</returns>
public static int GetStringValue(UIntPtr root, string keyName,
string valueName, ref string stringResult) {
UIntPtr hkey = UintPtr.Zero;
try {
int result = RegOpenKeyEx(root, keyName, 0, KeyAccess.None, ref hkey);
if (ERROR_SUCCESS != result) return result;
byte[] bytes = null;
uint length = 0;
KeyType keyType = KeyType.None;
result = RegQueryValueEx(hkey, valueName, IntPtr.Zero, ref keyType, null,
ref length);
if (ERROR_SUCCESS != result) return result;
keyType = KeyType.None;
bytes = new byte[length];
result = RegQueryValueEx(hkey, valueName, IntPtr.Zero, ref keyType, bytes,
ref length);
if (ERROR SUCCESS != result) return result;
stringResult = Encoding.Unicode.GetString(bytes, 0, bytes.Length);
return ERROR_SUCCESS;
} finally {
if (UIntPtr.Zero != hkey) {
RegCloseKey(hkey);
}
}
}
/// <summary>
/// Получает заданное значение типа DWORD.
/// </summary>
/// <param name="кеуNаmе">Имя ключа</раrаm>
/// <param name="vаluеNаmе">Имя параметра</раrаm>
/// <param name="dwоrdRеsult">Значение параметра</раrаm>
/// <returns>B успешной случае возвращается.
/// ERROR_SUCCESS</returns>
public static int GetDWORDValue(UIntPtr root, string keyName,
string valueName, ref uint dwordResult) {
UIntPtr hkey = UintPtr.Zero;
try {
int result = RegOpenKeyEx(root, keyName, 0, KeyAccess.None, ref hkey);
if (ERROR_SUCCESS != result) return result;
byte[] bytes = null;
uint length = 0;
KeyType keyType = KeyType.None;
result = RegQueryValueEx(hkey, valueName, IntPtr.Zero, ref keyType, null,
ref length);
bytes = new byte[Marshal.SizeOf(typeof(uint))];
length = (uint)bytes.Length;
keyType = KeyType.None;
result = RegQueryValueEx(hkey, valueName, IntPtr.Zero, ref keyType, bytes,
ref length);
if (ERROR_SUCCESS != result) return result;
dwordResult = BitConverter.ToUInt32(bytes, 0);
return ERROR_SUCCESS;
} finally {
if (UIntPtr.Zero != hkey) {
RegCloseKey(hkey);
}
}
}
/// <summary>
/// Удаляет заданный параметр из раздела реестра.
/// </summary>
/// <param name="кеуNаmе">Имя ключа</раrаm>
/// <param name="vаluеNаmе">Имя параметра</раrаm>
/// <rеturns>В успешном случае возвращается.
/// ERROR_SUCCESS</returns>
public static int DeleteValue(UIntPtr root, string keyName,
string valueName) {
UIntPtr hkey = UIntPtr.Zero;
try {
int result = RegOpenKeyEx(root, keyName, 0, KeyAccess.None, ref hkey);
if (ERROR_SUCCESS != result) return result;
return RegDeleteValue(hkey, valueName);
} finally {
if (UIntPtr.Zero != hkey) {
RegCloseKey(hkey);
}
}
}
/// <summary>
/// Типы ключей.
/// </summary>
public enum KeyType : uint {
None = 0,
String = 1,
Binary = 3,
Dword = 4,
}
/// <summary>
/// Тип доступа.
/// </summary>
public enum KeyAccess : uint {
None = 0x0000,
QueryValue = 0x0001,
SetValue = 0x0002,
CreateSubKey = 0x0004,
EnumerateSubKeys = 0x0008,
Notify = 0x0010,
CreateLink = 0x0020.
}
/// <summary>
/// HKEY_CLASSES_ROOT.
/// </summary>
public static UIntPtr HKCR = new UintPtr(0x80000000);
/// <summary>
/// HKEY_CURRENT_USER.
/// </summary>
public static UIntPtr HKCU = new UIntPtr(0x80000001);
/// <summary>
/// HKEY_LOCAL_MACHINE.
/// </summary>
public static UIntPtr HKLM = new UIntPtr(0x80000002);
/// <summary>
/// HKEY_USERS.
/// </summary>
public static UIntPtr HKU = new UintPtr(0x80000003);
/// <summary>
/// Возвращаемое значение в случае успеха.
/// </summary>
public const int ERROR_SUCCESS = 0;
/// <summary>
/// Функция для создания заданного раздела реестра. Если раздел.
/// уже существует, то функция открывает его.
/// </summary>
/// <param name="hkey">[in] Дескриптор к открываемому разделу.
/// или одна из ветвей реестра:
/// HKCR, HKCU, HKLM.</param>
/// <param name="lpSubKey">[in] Имя для нового раздела. Данный.
/// раздел должен быть подразделом раздела, определенного в.
/// параметре hKey.
/// </param>
/// <param name="Reserved">[in] Зарезервированный параметр.
/// Установлен равным 0</param>
/// <param name="lpClass">[in] Имя класса или типа объекта.
/// Данный параметр игнорируется, если раздел уже существует.
/// </param>
/// <param name="dwOptions">[in] Игнорируется; установите.
/// равным 0.
/// </param>
/// <param name="samDesired">[in] Игнорируется; установите.
/// равным 0.
/// </param>
/// <param name="lpSecurityAttributes">[in] Установите в NULL.
/// </param>
/// <param name="phkResult">[out] Переменная, получаемая от.
/// дескриптора нового или открытого раздела.
/// Если вы больше не нуждаетесь в дескрипторе, то вызовите.
/// функцию RegCloseKey для его закрытия. </param>
/// <param name="lpdwDisposition">[out] Переменная, которая.
/// получает значение 1 (REG_CREATED_NEW_KEY),
/// если раздел был создан.
/// и значение 2 (REG_OPENED_EXISTING_KEY), если был открыт уже.
/// существующий раздел.
/// </param>
/// <returns>ERROR_SUCCESS сообщает об успешном вызове функции.
/// В случае ошибки возвращается ненулевое значение.
/// </returns>
[DllImport("coredll.dll", SetLastError = true)].
public static extern int RegCreateKeyEx(
UIntPtr hkey, String lpSubKey, uint Reserved, StringBuilder lpClass,
uint dwOptions, KeyAccess samDesired, IntPtr lpSecurityAttributes,
ref UIntPtr phkResult, ref uint lpdwDisposition);
/// <summary>
/// Функция для удаления раздела реестра.
/// </summary>
/// <param name="hkey">[in] Дескриптор к удаляемому разделу или.
/// одна из ветвей реестра: HKCR, HKCU, HKLM.
/// </param>
/// <param name="subkeyName">[in] Имя удаляемого раздела.
/// Нельзя использовать NULL.
/// </param>
/// <returns>ERROR_SUCCESS сообщает об успешном вызове функции.
/// В случае ошибки возвращается ненулевое значение.
/// </returns>
[DllImport("coredll.dll", SetLastError = true)].
public static extern int RegDeleteKey(UIntPtr hkey, string subkeyName );
/// <summary>
/// Функция для открытия заданного раздела реестра.
/// </summary>
/// <param name="hkey">[in] Дескриптор к открываемому разделу.
/// или одна из ветвей реестра HKCR, HKCU, HKLM.</param>
/// <param name="lpSubKey">[in] Имя открываемого раздела.
/// </param>
/// <param name="ulOptions">[in] Зарезервированный параметр.
/// Установлен равным 0</param>
/// <param name="samDesired">[in] He поддерживается. Установите.
/// в 0.</param>
/// <param name="phkResult">[out] Переменная, получаемая от.
/// дескриптора открытого раздела. Если вы больше не нуждаетесь.
/// в дескрипторе, то вызовите функцию RegCloseKey для его.
/// закрытия</раrаm>
/// <returns>ERROR_SUCCESS сообщает об успешном вызове функции.
/// В случае ошибки возвращается ненулевое значение.
/// </returns>
[DllImport("coredll.dll", SetLastError = true)].
public static extern int RegOpenKeyEx(
UIntPtr hkey, String lpSubKey, uint ulOptions, KeyAccess samDesired,
ref UIntPtr phkResult);
/// <summary>
/// Функция получает тип и данные из заданного раздела реестра.
/// </summary>
/// <param name="hkey">[in] Дескриптор к открываемому разделу.
/// или одна из ветвей реестра: HKCR, HKCU, HKLM.</param>
/// <param name="lpValueName">[in] Значение параметра.
/// </param>
/// <param name="lpReserved">[in] Зарезервированный параметр.
/// Установите в NULL.</param>
/// <param name="lpType">[out] Тип данных.
/// </param>
/// <param name="lpData">[out] Буфер, получающий данные.
/// Данный параметр может быть NULL, если данные не требуются.
/// </param>
/// <param name="lpcbData">[in/out] Размер буфера в байтах.
/// </param>
/// <returns>ERROR_SUCCESS сообщает об успешном вызове функции.
/// В случае ошибки возвращается ненулевое значение.
/// </returns>
[DllImport("coredll.dll", SetLastError = true)].
public static extern int RegQueryValueEx(
UIntPtr hkey, String lpValueName, IntPtr lpReserved, ref KeyType lpType,
byte[] lpData, ref uint lpcbData);
/// <summary>
/// Функция создает параметр в разделе реестра.
/// </summary>
[DllImport("coredll.dll", SetLastError = true)].
public static extern int RegSetValueEx(
UIntPtr hkey, String lpValueName, uint Reserved, KeyType dwType,
byte[] lpData, uint cbData);
[DllImport("coredll.dll", SetLastError = true)].
public static extern int RegDeleteValue(UIntPtr hkey, string valueName);
[DllImport("coredll.dll", SetLastError = true)].
public static extern int RegCloseKey(UIntPtr hkey);
}
}
Наличие внешней клавиатуры.
С помощью класса Registry разработчик может получать или устанавливать значения параметров в реестре. Предположим, что нужно узнать, подключена ли к устройству внешняя клавиатура. За данную функцию отвечает параметр HasKeyboard в разделе HKEY_CURRENT_USER\Software\Microsoft\Shell. Если данный параметр имеет единичное значение, то система работает с подключенной внешней клавиатурой. Если значение равно нулю, то клавиатуры нет. В листинге 13.18 приведен код, показывающий, как можно извлечь значение интересующего параметра.
Листинг 13.18.
Private void butCheckKeyboard_Click(object sender, EventArgs e) {
uint check = 0;
Registry.GetDWORDValue(Registry.HKCU, "SOFTWARE\\Microsoft\\Shell",
"HasKeyboard", ref check);
lblInfo.Text = Convert.ToBoolean(check).ToString();
}
В этом примере используется функция-оболочка GetDWORDValue из класса Registry. Если же вы предпочитаете обходиться без функций-оболочек, а обращаться напрямую к функциям API, то пример можно переписать так, как показано в листинге 13.19.
Листинг 13.19.
Private static bool IsKeyboard() {
uint dwordResult;
UIntPtr hkey = UIntPtr.Zero;
try {
int result =
Registry.RegOpenKeyEx(Registry.HKCU, "SOFTWARE\\Microsoft\\Shell", 0,
Registry.KeyAccess.None, ref hkey);
if (Registry.ERROR_SUCCESS != result) return false;
byte[] bytes = null;
uint length = 0;
Registry.KeyType keyType = Registry.KeyType.None;
result =
Registry.RegQueryValueEx(hkey, "HasKeyboard", IntPtr.Zero, ref keyType,
null, ref length);
if (Registry.ERROR_SUCCESS != result) return false;
bytes = new byte[Marshal.SizeOf(typeof(uint))];
length = (uint)bytes.Length;
keyType = Registry.KeyType.None;
result =
Registry.RegQueryValueEx(hkey, "HasKeyboard", IntPtr.Zero, ref keyType,
bytes, ref length);
if (Registry.ERROR_SUCCESS != result) return false;
dwordResult = BitConverter.ToUInt32(bytes, 0);
return (dwordResult == 1);
} finally {
if (UIntPtr.Zero != hkey) {
Registry.RegCloseKey(hkey);
}
}
}
Теперь эту функцию можно вызвать в любом месте программы, как показано в листинге 13.20.
Листинг 13.20.
// Определяем наличие внешней клавиатуры.
LblInfo.Text = IsKeyboard().ToString();
ВНИМАНИЕ. Следует, отметить, что при проверке примера на эмуляторе функция обнаруживает присутствие клавиатуры. Что, в общем-то, справедливо, так как с помощью обычной клавиатуры пользователь может вводить данные в программах, запущенных на эмуляторе.Информация о пользователе.
Также с помощью реестра можно узнать информацию о пользователе устройства. За эту информацию отвечает параметр Owner в разделе HKEY_CURRENT_USER\ControlPanel\Owner. В листинге 13.21 приведен код, который получает эту информацию.
Листинг 13.21.
Private void butOwner_Click(object sender, EventArgs e) {
string strOwner = "";
Registry.GetStringValue(Registry.HKCU, "\\ControlPanel\\Owner", "Owner",
ref strOwner);
lblInfo.Text = strOwner;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.