Программирование КПК и смартфонов на .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;

}