Библиотека для работы с реестром c. Постоянно приходится указывать путь на дистрибутив Windows

22.03.2019

Реестр Windows является одной из самых загадочных частей операционной системы, которая позволяет настраивать и модифицировать почти все аспекты Windows. Некоторые работают с реестром постоянно, но большинство людей имеют о нем лишь слабое представление и не совсем уверены, как создавать пользовательские разделы и параметры. Итак, давайте попробуем разобраться, что же такое реестр Windows.

Что такое реестр Windows

Реестр Windows – это не что иное, как совокупность различных конфигураций и настроек системы.

Его можно рассматривать как базу данных, хранящую практически всю важную информацию. Эта информация включает в себя все то, что связанно с системой аппаратного обеспечения, настройками приложений, установленными программами, профилями пользователей и т.д. Windows обращается к реестру постоянно, поскольку, как уже было сказано, в нем хранится вся важная информация, и операционной системе гораздо быстрее и проще управлять всем из одного места, чем возиться с отдельными файлами конфигурации, расположенными в разных местах.

Компоненты реестра Windows

Реестр Windows 10 состоит из трех основных компонентов – ключи корневого уровня, разделы и параметры.

Ключи корневого уровня содержат в себе разделы, которые имеют свой собственный набор параметров.

Существует пять различных ключей корневого уровня, и все они имеют свои собственные специфические цели. Вот их суть:

  • HKEY_CLASSES_ROOT (HKCR): этот ключ используется для связывания и внедрения объектов (Object Linking and Embedding, OLE) и ассоциации типов файлов. Это ключ, где Windows связывает файлы с их соответствующими программами, чтобы пользователь мог открывать и взаимодействовать с ними.
  • HKEY_ CURRENT_ USER (HKCU): этот раздел реестра Виндовс хранит все данные, настройки на уровне пользователя и конфигурации, связанные с вошедшим в систему пользователем. Не только Windows, но и другие программы хранят здесь данные, относящиеся к текущему пользователю.
  • HKEY_LOCAL_MACHINE (HKLM): независимо от статуса пользователя, этот ключ содержит все системные разделы, в том числе любые аппаратные настройки, параметры программного обеспечения и т.д. Поскольку HKLM содержит большую часть всей системной информации, он является одним из самых открытых корневых ключей Windows.
  • HKEY_USERS (HKU): как следует из названия, этот корневой ключ содержит параметры всех пользователей, включая вошедших и вышедших из системы, так что не путайте этот ключ с HKCU.
  • HKEY_CURRENT_CONFIG (HKCC): проще говоря, это псевдо корневой ключ, поскольку он является прямой ссылкой на текущие параметры профиля оборудования в корневом ключе HKLM.

Параметры разделов

Каждый из этих корневых ключей имеет свои собственные разделы, а каждый раздел имеет свои собственные параметры. В каждом разделе можно создать 6 различных типов параметров, а значения этих параметров полностью зависят от целевой программы и/или требований к конфигурации.

А вообще есть четыре основных типа данных, используемых в редакторе реестра Windows любой версии - 7,8 или 10:

  • Строковый параметр: состоит из простого читаемого текста и является одним из наиболее часто используемых параметров в реестре Windows.
  • Двоичный параметр: как следует из названия, этот параметр содержит только двоичные данные (0, 1). Часто используется для включения или выключения определенной функции.
  • Параметр DWORD (32 бита): похож на двоичный параметр, но способен хранить любое целое число в диапазоне от 32 бит. Предназначен для работы с 32-битными системами, но также используется в 64-битных системах в целях обеспечения обратной совместимости.
  • Параметр QWORD (64 бита): этот параметр почти как DWORD, но способен нести любое целое число в диапазоне от 64 бит. Можно сказать, что QWORD предназначен для работы с 64-битными системами.

Как открыть редактор реестра Windows

Этот способ открытия реестра будет работать независимо от установленной версии Windows - 7,8 или 10:

Нажмите клавишу + клавишу R, чтобы открыть окно «Выполнить». Введите или и нажмите Enter или OK. Если появится окно контроля учетных записей (UAC), нажмите «Да».

Основной исполняемый файл редактора реестра находится в каталоге C:\Windows . Так что можно открыть эту папку и запустить файл regedit.exe напрямую, или можно просто создать ярлык regedit.exe в удобном для вас месте.

Редактор реестра: для 64-разрядных и 32-разрядных Windows

Реестр в 64-битных версиях Windows состоит из 32-битных и 64-битных разделов. Многие из 32-битных разделов имеют те же самые названия, что и их 64-битные аналоги, и наоборот.

64-разрядная версия (используется по умолчанию) (regedit.exe) отображает как 64-битные, так и 32-битные разделы. В 64-разрядной версии редактора реестра 32-битные ключи отображаются в следующем разделе реестра:

HKEY_LOCAL_MACHINE\Software\WOW6432Node

Просматривать и редактировать 64-битные и 32-битные разделы и параметры можно с помощью 64-разрядной версии редактора. Для просмотра или редактирования 64-битных ключей необходимо использовать 64-разрядную версию редактора реестра (regedit.exe). Редактировать и просматривать 32-битные ключи и значения можно также с помощью 32-разрядной версии (%systemroot\%Syswow64). Чтобы открыть 32-разрядную версию редактора реестра, выполните следующие действия:

  • Откройте диалог «Выполнить».
  • Введите %systemroot%\syswow64\regedit и нажмите OK.

Примечание

Перед открытием 32-разрядной версии нужно закрыть 64-разрядную версию редактора реестра (и наоборот). Однако можно открыть второй экземпляр редактора реестра. Например, если 64-битная версия редактора уже запущена, введите команду %systemroot%\syswow64\regedit -m , чтобы запустить 32-разрядную версию редактора.

Создание новых разделов и параметров

Создавать разделы и параметры очень просто. Но прежде чем что-либо делать, пожалуйста, создайте резервную копию реестра Windows, так как любые неверные настройки или удаление важных элементов может стать причиной критических ошибок.

Чтобы создать резервную копию, в окне редактора нажмите «Файл -> Экспорт», введите имя файла и сохраните его в надежном месте.

Чтобы создать новый раздел, щелкните правой кнопкой мыши на ключе корневого уровня и выберите «Создать -> Раздел». Новый раздел будет выглядеть как папка, и по умолчанию будет называться что-то вроде «Новый раздел #1». Разумеется, раздел можно всегда переименовать. Такая же процедура применяется всякий раз, когда нужно создать новый подраздел.

Чтобы создать новый параметр, щелкните правой кнопкой мыши в пустой области правой панели редактора и выберите нужный параметр. Созданному параметру нужно присвоить название; название полностью зависит от конкретных требований.

Чтобы присвоить параметру значение, дважды щелкните на нем и введите значение. Опять же, значение зависит от программы или конкретных настроек.

Права доступа к разделам реестра

По аналогии с правами и разрешениями на определенные объекты в файловой системе NTFS, такая же защита предусмотрена и для разделов реестра.

Еще со времен Windows Vista большое количество ОС-специфических ключей реестра, хранящих настройки Windows, находятся под защитой Windows Resource Protection, поэтому нельзя просто взять и удалить или изменить их. Вы не сможете сделать этого, не став их владельцем и не установив разрешения (права доступа) на них. К счастью, операционная система позволяет и это, но ручной способ чересчур муторный, поэтому лучше использовать простую утилиту , которая автоматизирует весь этот процесс.

На этом все! Надеюсь, написанное выше помогло вам лучше понять реестр Windows и его основные компоненты. Обменивайтесь мнениями и опытом в комментариях ниже!

Отличного Вам дня!

Реестр Windows является неотъемлемой частью каждой операционной системы Microsoft Windows. Он действует так, же как каталог, в котором хранятся все виды пользовательских настроек, конфигурационных данных о приложениях, файловые ассоциации и т.д. Если попробовать дать определение этого чудо-компонента, то реестр - компонент операционной системы компьютера, который в иерархической базе данных хранит важнейшие установки и информацию о приложениях, системных операциях и пользовательской конфигурации. Таким образом, возможность работы с реестром – это что-то, что не может быть упущено из виду разработчиком Windows приложений.

В этой статье я попытаюсь рассказать Вам, как использовать возможности этого монстра в c++ приложениях.Мы подойдем к этой ситуации с помощью специальных API-функций, которые позволяют работать с реестром. В этой статье мы узнаем, как создать консольное приложение, позволяющее открыть указанный раздел, создать и установить новое значение, создать новый подраздел, удалить подраздел и значение. При этом мы не будем использовать никаких дополнительных библиотек.

Однако для начала разберемся со структурой реестра, а затем приступим к написанию программы, объясняя правильное использование каждой функции реестра.

Я не буду подробно описывать структуру этого монстра от Microsoft. Я всего лишь расскажу достаточную информацию для понятия этой статьи. Всю, необходимую Вам, информацию Вы сможете найти в сети.

Структура реестра

Важно понять структуру реестра на данном этапе усваивания материала, что бы потом у нас не возникло непонимания по ходу дальнейшего изучения. В этом разделе мы очень быстро и кратко «пробежимся» по реестру, т.к. на подробное его изучение потребуется много времени и места. Представьте реестр как папку. В ней могут быть другие папки и файлы. Теперь разберемся с обозначением. Реестр Windows содержит два элемента: раздел (key) и значение (value). В нашей аналогии разделы выступают в роли папок, в то время как значения – файлы. В действительности, значения – это пары «имя-данные». Это значит, что значение делится на две части: имя и данные. Имя используется как идентификатор, а данные как часть фактических данных. Каждый раздел имеет значение, но, помимо значения, раздел может иметь и подраздел. Весь реестр делится на логические разделы, которые называются «ульи» (hives). Всего таких разделов пять.

Теперь зайдите в редактор реестра (Пуск-Выполнить-regedit) и посмотрите его структуру. На всякий случай сделайте копию реестра. Хотя наша программа будет безобидной для него, лишним это действие все равно не будет. Для тех, кто не знает, я расскажу, как сделать копию реестра.

Что бы сделать backup своего реестра выполните следующие действия:
1) Нажмите "Пуск", "Выполнить" и введите "regedit".
2) Появится окно редактора реестра. Нажмите в верхней части окна "Файл", потом "Экспорт". Введите любое имя для сохраняемого резервного файла реестра, тип файла выберите "Файлы реестра *.reg". Ниже, под надписью "Диапазон экспорта" выберите "Весь реестр", нажмите "Сохранить".

Теперь разберем некоторые функции, которые нам понадобятся для написания задуманного.

Базовые функции реестра

В этой статье мы узнаем, как читать, изменять и записывать данные в реестр. По ходу этого раздела мы рассмотрим некоторые из основных функций для открытия подразделов реестра и работы с ними. Функции, с которыми мы будем работать, Вы сможете найти в файле windows.h. Эти функции работают с любой версией Windows.

Наша первая функция - RegOpenKeyEx (). Эта функция открывает указанный раздел реестра и возвращает ERROR_SUCCESS при успешном выполнении. Важно понять, что эта функция открывает уже существующий раздел; она не создаст новый раздел, если такового не существует.

Вторая функция, которую мы будем использовать – это функция RegSetValueEx(), которая создает новое значение в нашем разделе, открытом с помощью первой рассмотренной функции.

Следующие три функции позволят добавить новый раздел и удалить данные с реестра. RegCreateKeyEx () будет использоваться для создания нового ключа, а при удалении значения и ключа мы будем вызывать RegDeleteValue () и RegDeleteKey () соответственно. Если Вы пользователь Windows Vista или Microsoft Server 2008, то вместо функции RegDeleteValue () Вам следует вызвать функцию RegDeleteTree(). Хотя чаще возникает потребность писать универсальное приложение, которое будет работать с любым продуктом Microsoft. Поэтому делайте проверку WINWER в своем коде.

Ну и последняя функция, которая нам понадобится в данном уроке – это функция, которая уничтожает (а лучше сказать освобождает) переменную, в которой будет храниться дескриптор, открытого с помощью первой функции, раздела. Имя этой функции RegCloseKey().
Теперь мы знакомы с функциями (а точнее с их именами и назначением), которые нам пригодятся, и переходим к написанию кода нашей программы.

Как понятно из названия данного раздела, тут будет код нашей программы. Но перед тем, как писать код необходимо создать пустое консольное приложение. Я использую Microsoft Visual Studio 2010. О том, как создать, необходимый нам, тип приложения подробно описано в последнем номере журнала () в статье "Что нам стоит GUI построить".

Тут я приведу сразу весь код, а потом прокомментирую его, дав подробное описание каждой функции.
int main()
{
HKEY hKey;
DWORD dwDisposition;
unsigned char szStr;
szStr="1"; szStr="\0";

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online\\Test"), 0, KEY_ALL_ACCESS, &hKey)!=ERROR_SUCCESS)
cout<<"\nError opening the desired subkey (doesn"t exist?).\n";
else
{

cout<<"\nThe value of the key was set successfully.\n";
else
cout<<"\nError setting the value of the key.\n";
}
RegCloseKey(hKey);

RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online\\Test\\Another SubKey"), 0, NULL, 0, 0, NULL, &hKey, &dwDisposition);
if (dwDisposition != REG_CREATED_NEW_KEY && dwDisposition != REG_OPENED_EXISTING_KEY)
cout<<"\nError creating the desired subkey (permissions?).\n";
else
cout<<"\nThe subkey was successfully created.\n";
RegCloseKey(hKey);


{

cout<<"\nString Value value successfully removed.\n";
else
cout<<"\nError removing the specified value (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online\\Test"), 0, KEY_ALL_ACCESS, &hKey)==ERROR_SUCCESS)
{

cout<<"\nAnother SubKey key successfully removed.\n";
else
cout<<"\nError removing the specified key (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);


{

cout<<"\nTest key successfully removed.\n";
else
cout<<"\nError removing the specified key (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);


{

cout<<"\nVR_Online key successfully removed.\n";
else
cout<<"\nError removing the specified key (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);

Ну, что же, теперь надо разобраться, что тут написано.
HKEY hKey;
DWORD dwDisposition;
unsigned char szStr;
szStr="1"; szStr="\0";

В первой строке мы объявили переменную hKey, типа HKEY. Это переменная – дескриптор указанного «улья» реестра. Во второй строке объявлена переменная, dwDisposition, которая нужна для определения, является ли подраздел созданным или он уже существовал, и может ли он быть открыт успешно. Данная переменная понадобится нам для функции RegCreateKeyEx (). Подробно о значениях, которые функция загоняет в эту переменную, Вы сможете узнать на msdn.com в описании данной функции. Далее мы объявили массив типа unsigned char, состоящий из двух элементов. Первому элементу мы присвоили значение «1», а второму – конец строки. Эта переменная (массив) будет служить данными для нашего имени при создании нового значения функцией RegSetValueEx().
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online\\Test"), 0, KEY_ALL_ACCESS, &hKey)!=ERROR_SUCCESS)
cout<<"\nError opening the desired subkey (doesn"t exist?).\n";
else
{
if (RegSetValueEx(hKey, TEXT("String Value"), NULL, REG_SZ, szStr, sizeof(szStr))==ERROR_SUCCESS)
cout<<"\nThe value of the key was set successfully.\n";
else
cout<<"\nError setting the value of the key.\n";
}
RegCloseKey(hKey);

В вышеприведенном куске кода мы проверяем успешное выполнение функции RegOpenKeyEx(). Описание этой функции приведено выше. Т.к. эта функция открывает уже существующий раздел то, выполнение этой функции выдаст нам сообщение об ошибке. Что бы этого избежать, можно создать «вручную» этот раздел, а можно и программно. Давайте создадим его «вручную», т.к. далее вы узнаете, как создавать разделы программно. Что бы «вручную» создать раздел, необходимо войти в редактор реестра (Пуск-Выполнить-regedit), выбрать нужным нам «улей» (в нашем случае HKEY_LOCAL_MACHINE). В нем выбираем раздел «SOFTWARE» (кстати, в нашей функции, как и во всех функциях работы с реестром регистр букв не важен), жмем на него правой клавишей мыши и «Создать»-«Раздел». Присваиваем разделу имя VR_Online, а потом в нем создаем подраздел с именем «Test» аналогичным образом.

Первый параметр функции – раздел реестра, который мы хотим открыть. Второй – имя подраздела. В данном примере мы открыли подраздел “SOFTWARE” По поводу третьего параметра документация Microsoft говорит только то, что он зарезервирован и должен быть равным нулю. Четвертый параметр – уровень доступа. В данном примере мы получили полный доступ к этому разделу. Однако не всегда раздел позволят получить к нему полный доступ, в таком случае функция будет выполнена неудачно. Последний параметр этой функции – указатель на переменную, которой будет передан дескриптор открытого раздела.

Если раздел существует, то мы устанавливаем ему значение (помните я говорил, что значение есть пара «имя-данные»?). Именем значения будет «String Value», а данными – наш массив szStr. Создаем мы значение с помощью функции RegSetValueEx(),в которую последовательно передаем дескриптор раздела, название переменной, тип данных (с типами данных Вы можете ознакомиться на msdn - http://msdn.microsoft.com/en-us/library/ms724884 (v=vs.85).aspx), сейчас только скажу, что этот тип значит строковую переменную. Последние два параметра – указатель на буфер данных и его размер. О результате выполнения этой функции на экран выводится сообщение. В конце мы вызываем функцию RegCloseKey().

Далее мы программно создадим подраздел. Делается это с помощью функции RegCreateKeyEx ().
RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online\\Test\\Another SubKey"), 0, NULL, 0, 0, NULL, &hKey, &dwDisposition);

if (dwDisposition != REG_CREATED_NEW_KEY && dwDisposition != REG_OPENED_EXISTING_KEY)
cout<<"\nError creating the desired subkey (permissions?).\n";
else
cout<<"\nThe subkey was successfully created.\n";
RegCloseKey(hKey);

Первые два параметра, а так же предпоследний параметр, понятны исходя из уже известного материала. Про последний параметр я рассказал выше, при описании, объявленных в начале функции main(), переменных. Третий параметр зарезервирован и должен равняться нулю. Четвертый – тип класса раздела. В пятом параметре могут содержаться дополнительные опции, значение которых можно глянуть в описании этой функции на msdn. Следующий параметр определяет спецификатор доступа к данному разделу. Седьмой параметр является атрибутом безопасности. Он определяет, может ли данный раздел (а точнее его дескриптор) наследоваться дочерными процессами. Если он в значении NULL, то дескриптор не может быть унаследован.

А теперь очистим наш реестр от всего того, что мы создали.
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online\\Test"), 0, KEY_ALL_ACCESS, &hKey)==ERROR_SUCCESS)
{
if (RegDeleteValue(hKey, TEXT("String Value"))==ERROR_SUCCESS)
cout<<"\nString Value value successfully removed.\n";
else
cout<<"\nError removing the specified value (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online\\Test"), 0, KEY_ALL_ACCESS, &hKey)==ERROR_SUCCESS)
{
if (RegDeleteKey(hKey, TEXT("Another SubKey"))==ERROR_SUCCESS)
cout<<"\nAnother SubKey key successfully removed.\n";
else
cout<<"\nError removing the specified key (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\VR_Online"), 0, KEY_ALL_ACCESS, &hKey)==ERROR_SUCCESS)
{
if (RegDeleteKey(hKey, TEXT("Test"))==ERROR_SUCCESS)
cout<<"\nTest key successfully removed.\n";
else
cout<<"\nError removing the specified key (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software"), 0, KEY_ALL_ACCESS, &hKey)==ERROR_SUCCESS)
{
if (RegDeleteKey(hKey, TEXT("VR_Online"))==ERROR_SUCCESS)
cout<<"\nVR_Online key successfully removed.\n";
else
cout<<"\nError removing the specified key (permissions?).\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey(hKey);

Что ж…тут только две новых функции: RegDeleteValue() и RegDeleteKey(). Их назначение понятно из их названий, а параметры понятны из усвоенного материала и простой интуиции. Как Вы могли заметить, эта часть кода обладает значительным минусом – нельзя удалить сразу раздел VR_Online со всем его содержимым. Удалять надо, начиная с «глубин» подраздела. Но заинтересовавшиеся читатели могут попробовать написать рекурсивную функцию, которая сама будет это делать.

Я вот еще раз перечитал свою статью и понял, что чего-то тут не хватает. Дело в том, что чаще приходится использовать данные реестра, а не изменять их или добавлять данные в реестр. Поэтому, как бонус, тем, кто дочитал до этого места, я рассажу, как с помощью реестра получить адрес стартовой страницы Internet Explorer, а затем изменить его. И хотя этим браузером мало кто пользуется, технология получения подобной информации одинакова. Для начала установим значение стартовой страницы. Сделать это можно тремя способами: через редактор реестра вручную, через браузер и программно. Т.к. наша тема связана с реестром, а программно мы изменим значение позже, то сейчас мы это сделаем вручную.

Заходим в «Пуск» - «Выполнить» и пишем regedit. В редакторе реестра проходи по пути «Software\\Microsoft\\Internet Explorer\\Main» и находим там значение Start Page. Жмем на эту переменную два раза и в появившемся диалоговом окне в поле «значение» указываем, например, «http://google.com”.

Следующий код Вы можете использовать как раз для достижения нашей «бонусной» цели.
TCHAR lpData={0};
DWORD buffersize = sizeof(lpData);

If (RegOpenKeyEx (HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),NULL,KEY_READ,&hKey)==ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey,TEXT("Start Page"),NULL,NULL,(LPBYTE) lpData,&buffersize)==ERROR_SUCCESS)
{
cout<<"\nYour current Internet start page is ";
wcout< }
else
cout<<"\nError getting the specified value.\n"
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey (hKey);

TCHAR *Val=_T("http://сайт");
DWORD size=_tcslen(Val);

if (RegOpenKeyEx (HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),NULL,KEY_ALL_ACCESS,&hKey)==ERROR_SUCCESS)
{
if (RegSetValueEx(hKey, TEXT("Start Page"),0, REG_SZ, (BYTE*)Val,2*size)==ERROR_SUCCESS)
{
cout<<"\nNow your Internet start page is ";
wcout< }
else
cout<<"\nError setting the value of the key.\n";
}
else
cout<<"\nError opening the specified subkey path (doesn"t exist?).\n";

RegCloseKey (hKey);

Как видно из кода, у нас только одна неизвестная нам функция. RegQueryValueEx(). Она позволяет получить значение, которое хранится в указанном разделе. Первые два параметра этой функции, я думаю, не стоит описывать. Третий зарезервирован. Четвертый параметр содержит тип получаемого значения. Два последних параметра определяют буфер, в который будет записано значение, и его размер соответственно. Ну а далее мы изменяем значение этой переменной с помощью,уже известной нам, функции.

Что бы Вам было более ясно происходящее в данном коде, я расскажу Вам о типах char, TCHAR и о кодировке UNICODE.

Вообще, по теме этого раздела стоит писать отдельную статью, которая по размерам не будет уступать этой статье, но я этого делать не буду, т.к. не обладаю глубокими знаниями в этой области. Я расскажу то, чего хватит для понимания моей статьи.

Тип char используется для ANSI строк, т.е. строк, символы которых занимают один байт (8 бит). То есть допускается всего 256 (2 в восьмой степени) символов. Гляньте в таблицу ASCII, и Вы увидите, что все символы там не выходят за значение 255. Этого количества символов хватает нам с Вами с нашим-то алфавитом. И тип char идеально подходит для содержания этих символов.

Но давайте подумаем о японцах. У них существуют различные наборы символов, такие как, например катакана (katakana), хирагана (hiragana), канжи (kanji) и ромаджи (romaji). Невозможно впихнуть все эти символы в диапазоне от нуля до 255. Поэтому и используется кодировка Unicode, которая может содержать 65535 (2 в шестнадцатой степени) символов.

В основном тип TCHAR и используется для описания Unicode строк. В отличие от типа char, tchar занимает 2 байта. Это и объясняет умножение на двойку длины строки, в которой содержится новое имя стартовой страницы.
if (RegSetValueEx(hKey, TEXT("Start Page"),0, REG_SZ, (BYTE*)Val,2*size)==ERROR_SUCCESS)

Т.к. продукты Microsoft используют по всему миру, то программисты этой компании потрудились над тем, что бы разработчикам приложений под их основной продукт было удобно пользоваться своим языком, а не вездесущим английским. Поэтому почти все API функции «зависят» от Unicode.
Для удобной работы с Unicode – строками существует файл tchar.h. В нем собрано огромное количество макросов для работы TCHAR. Макрос TEXT, взятый как раз из этой библиотеки, позволяет компилировать программу и под Unicode и под ANSI. Так же там описан оператор wcout, который работает аналогично cout, но для TCHAR-типа.
Я думаю, что материал этого раздела хоть как-то пролил свет на Ваше представление о происходящем.

Вот и все. Мы сделали все, что задумали в начале урока и даже больше. Я не стал наполнять эту статью скриншотами с результатами выполнения различных частей кода этой программы. Вы сами можете это сделать, поэтапно комментируя определенные функции и заглядывая в редактор реестра. Надеюсь, что кто-то нашел в этой статье что-нибудь полезное.

В заключение скажу, что реестр очень удобная вещь для разработчика. В нем вы можете хранить настройки своих приложений и использовать параметры других приложений, а так же настроек системы. Но не стоит изменять или удалять те значения и разделы, в ненадобности которых вы не уверены.

Если по каким-то причинам, у Вас не работает код, который я приводил в пример, ниже Вы можете скачать рабочий.cpp файл этой программы.

Спасибо за внимание.

Written by: Сергей Дубовик aka SD
E-mail: eval(unescape("%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%73%64%62%6f%78%40%74%75%74%2e%62%79%22%3e%73%64%62%6f%78%40%74%75%74%2e%62%79%3c%2f%61%3e%27%29%3b"))

Реестр

Во всех версиях Windows, начиная с Windows 95, системный реестр является центральным хранилищем всей конфигурационной информации, касающейся настройки Windows, пользовательских предпочтений, а также установленного программного и аппаратного обеспечения. Почти любое коммерческое программное обеспечение в наши дни использует реестр для хранения информации о себе.

Компонентам СОМ тоже требуется сохранять информацию о себе в реестре для того, чтобы клиенты могли к ним обращаться. Среда.NET Framework и предлагаемая в ней концепция установки с нулевым воздействием (zeroimpact installation) делает реестр чуть менее существенным для приложений, поскольку создаваемые с ее помощью сборки получаются полностью самодостаточными, т.е. никакой информации в реестр для них помещать не требуется, даже если они являются разделяемыми.

Вдобавок в.NET Framework предлагается концепция изолированного хранилища (приложения могут хранить информацию, касающуюся каждого пользователя, в файлах) и.NET Framework самостоятельно заботится об отдельном хранении данных для каждого зарегистрированного в системе пользователя.

Тот факт, что теперь приложения могут устанавливаться с помощью Windows Installer, освобождает разработчиков от необходимости производить манипуляции с реестром, без которых установка приложений ранее была невозможной. Однако, несмотря на это, остается вероятность, что распространяемое приложение будет использовать системный реестр для сохранения информации о своей конфигурации.

Например, если приложение должно появляться в диалоговом окне Add/Remove Programs (Установка и удаление программ) панели управления, потребуется внести соответствующие записи в системный реестр. Системный реестр также может понадобиться для обеспечения обратной совместимости с унаследованным кодом.

Как и следовало ожидать от такой обширной библиотеки, как.NET, в ней поставляются классы, которые позволяют получать доступ к реестру. Таких классов два - Registry и RegistryKey , и оба они находятся в пространстве имен Microsoft.Win32 . Прежде чем переходить к рассмотрению этих классов, давайте вкратце ознакомимся со структурой самого реестра.

Реестр имеет иерархическую структуру, во многом похожую на структуру файловой системы. Обычно для просмотра и изменения содержимого реестра применяются две утилиты: regedit и regedt32 . Утилита regedit является стандартной и поставляется во всех версиях Windows, начиная с Windows 95. Утилита regedt32 входит в состав Windows NT и Windows 2000, и по сравнению с regedit менее дружественная к пользователю, но зато она позволяет получать доступ информации, связанной с безопасностью, которую regedit просматривать не позволяет.

В Windows Server 2003 эти утилиты были объединены в единый новый редактор, который называется просто regedit. В ходе обсуждений здесь имеется в виду утилита regedit, поставляемая в Windows 7, которую можно запустить, введя regedit в диалоговом окне для запуска программ либо в командной строке.

На рисунке показано, как выглядит окно regedit при запуске этой утилиты в первый раз. На этом рисунке видно, что regedit имеет пользовательский интерфейс в стиле "дерево/список", который похож на интерфейс проводника Windows и в точности отражает иерархическую структуру самого реестра. Однако вскоре будут показаны и некоторые важные отличия:

В файловой системе узлы верхнего уровня представляют разделы дисков - С:\ , D:\ и т.д. В реестре эквивалентом разделов дисков являются разделы реестра (registry hive) . Изменять существующие разделы не допускается - они являются фиксированными и всего их семь, хотя в интерфейсе regedit видны только пять из них, которые перечислены ниже:

HKEY_CLASSES_ROOT (HKCR)

содержит детали, касающиеся типов файлов в системе (.txt, .doc и т.д.), и о том, какие приложения способны открывать файлы каждого из этих типов. Также содержит регистрационную информацию обо всех компонентах СОМ (она обычно занимает больше всего места в реестре, поскольку в Windows в настоящее время поставляется огромное количество разнообразных СОМ-компонентов).

HKEY_CURRENT_USER (HKCU)

содержит детали, касающиеся предпочтений пользователя, который в текущий момент локально работает в системе. К числу этих предпочтений относятся настройки рабочего стола, переменные окружения, подключение к сетям и принтерам и прочие параметры, которые определяют внешний вид рабочей среды пользователя.

HKEY_LOCAL_MACHINE (HKLM)

представляет собой огромный раздел, в котором содержатся детали, касающиеся всего установленного на машине программного и аппаратного обеспечения. Также включает в себя раздел HKCU, который сам по себе не является отдельным разделом, а просто удобным отображением ключа реестра HKLM/SOFTWARE/Classes.

HKEY_USERS (HKUSR)

содержит детали, касающиеся предпочтений всех пользователей. Как не трудно догадаться, он тоже содержит разделы HKCU, которые являются просто отображением соответствующих ключей HKEY_USERS.

HKEY_CURRENT_CONFIG (HKCF)

содержит детали, касающиеся конфигурации установленного на машине оборудования.

В остальных двух корневых разделах размещается информация, которая является временной и часто изменяющейся:

HKEY_DYN_DATA

является общим контейнером для любых текущих данных, которые требуется сохранять где-нибудь в реестре.

HKEY_PERFORMANCE_DATA

содержит информацию, касающуюся производительности функционирующих в текущий момент приложений.

Внутри разделов находится древовидная структура ключей реестра. Каждый из них во многом напоминает папку или файл в файловой системе. Однако между ними имеется одно очень важное отличие. В файловой системе различаются файлы (в которых хранятся данные) и папки (в которых главным образом содержатся другие файлы или папки), а в реестре присутствуют только ключи. В каждом ключе могут содержаться как данные, так и другие ключи.

Если ключ содержит данные, то они представлены последовательностью значений. Каждое значение имеет ассоциированное с ним имя, тип данных и собственно данные. Вдобавок ключ имеет безымянное значение по умолчанию.

Всю эту структуру можно увидеть, используя утилиту regedit. На рисунке показано содержимое ключа HKCU\Console:

Записи в системном реестре могут иметь формат одного из трех типов данных:

    REG_SZ (приблизительно соответствует экземпляру строки в.NET, но это сходство не точное, поскольку типы данных реестра не являются типами данных.NET);

    REG_DWORD (приблизительно соответствует типу uint);

    REG_BINARY (массив байт).

Приложение, предусматривающее сохранение каких-то данных в реестре, будет делать это за счет создания ряда ключей, причем обычно внутри ключа HKLM\Software\<Название компании>. Обратите внимание, что в этих ключах вовсе не обязательно должны содержаться какие-либо данные. Порой сам факт существования ключа позволяет приложению получать те данные, которые ему необходимы.

Как уже говорилось, доступ к реестру позволяют получать два класса из пространства имен Microsoft.Win32: Registry и RegistryKey. Экземпляр RegistryKey представляет ключ реестра. В этом классе есть методы для просмотра дочерних ключей, для создания новых ключей, а также для чтения и изменения значений в существующих ключах, т.е. можно выполнять все, что обычно требуется делать с ключами реестра, в том числе устанавливать для них уровни безопасности. Именно этот класс применяется для выполнения большей части работы с реестром.

В отличие от него, Registry представляет собой класс, который позволяет получать эксклюзивный доступ к ключам реестра для выполнения простых операций. Другим предназначением класса Registry является предоставление экземпляров RegistryKey, представляющих ключи наивысшего уровня, т.е. разделы, которые позволяют осуществлять навигацию по реестру. Предоставляются эти экземпляры через семь статических свойств со следующими именами: ClassesRoot, CurrentConfig, CurrentUser, DynData, LocalMachine, PerformanceData и Users. Каким разделам соответствуют эти свойства, должно быть вполне очевидно.

Например, для получения экземпляра RegistryKey, представляющего ключ HKLM, потребуется написать такой код:

RegistryKey hklm = Registry.LocalMachine;

Процесс получения ссылки на объект RegistryKey называется открытием ключа . Хотя можно было бы ожидать, что, поскольку реестр имеет такую же иерархическую структуру, что и файловая система, методы, предлагаемые классом RegistryKey, должны быть похожими на те, что реализованы в DirectoryInfo, на самом деле это не так. Часто способ доступа к реестру отличается от способа использования файлов и папок, и RegistryKey реализует методы, отражающие это.

Наиболее очевидное отличие связано с тем, как открывается ключ в определенном месте реестра. Класс Registry не имеет никакого общедоступного конструктора, который можно было бы использовать, равно как не имеет и методов, которые позволяли бы переходить к ключу по имени напрямую. Вместо этого добираться до нужного ключа придется от самого верхнего раздела.

Если необходимо создать экземпляр объекта RegistryKey, то единственно возможный способ предусматривает начать с соответствующего статического свойства класса Registry и оттуда уже двигаться вниз. То есть, например, для чтения данных из ключа HKLM\Software\Microsoft потребуется получить на него ссылку следующим образом:

RegistryKey hklm = Registry.LocalMachine; RegistryKey hkSoftware = hklm.OpenSubKey("Software"); RegistryKey hkMicrosoft = hkSoftware.OpenSubKey("Microsoft");

Доступ к ключу подобным образом позволяет осуществлять только чтение. Если необходимо выполнить запись каких-то данных в ключ (в том числе запись его значения, а также создание или удаление его непосредственных дочерних элементов), потребуется использовать другую переопределенную версию OpenSubKey . Она принимает во втором параметре значение типа bool, указывающее, должен ли доступ к ключу предоставляться не только для чтения, но и для записи. Например, чтобы получить возможность изменить ключ Microsoft (имея права системного администратора), потребуется написать следующий код:

RegistryKey hklm = Registry.LocalMachine; RegistryKey hkSoftware = hklm.OpenSubKey("Software"); RegistryKey hkMicrosoft = hkSoftware.OpenSubKey("Microsoft", true);

Кстати, поскольку в этом ключе содержится информация, используемая приложениями Microsoft, в большинстве случаев этот конкретный ключ модифицировать не стоит.

Метод OpenSubKey() вызывается в случаях, когда ожидается, что ключ уже существует. Если ключа там не оказывается, OpenSubKey() возвращает ссылку null. Чтобы создать ключ, необходимо использовать метод CreateSubKey() (который автоматически предоставляет доступ как для чтения и записи к ключу через возвращаемую ссылку):

RegistryKey hklm = Registry.LocalMachine; RegistryKey hkSoftware = hklm.OpenSubKey("Software"); RegistryKey hkMine = hkSoftware.CreateSubKey("MyOwnSoftware");

Способ, которым работает метод CreateSubKey(), является довольно интересным. Он создает ключ, если его не существует, а если ключ существует, метод просто возвращает экземпляр RegistryKey, который представляет существующий ключ. Причина, по которой этот метод ведет себя подобным образом, связана с тем, как обычно используется реестр. В реестре в целом содержатся подлежащие длительному хранению данные наподобие конфигурационной информации для Windows и различных приложений. Поэтому необходимость создавать ключ явным образом возникает не очень часто.

Гораздо чаще приложениям требуется проверять наличие некоторой информации в реестре - другими словами, создавать ключи, если они еще не существуют, и ничего не делать, если ключи уже там есть. Метод CreateSubKey() просто идеально позволяет удовлетворить такую потребность. В отличие от ситуации с FileInfo.Open(), в случае применения CreateSubKey() случайное удаление каких-нибудь данных исключается. Если же на самом деле необходимо удалить какие-то ключи реестра, потребуется вызвать метод DeleteSubKey() .

Учитывая важность реестра для Windows, в этом есть смысл. Вряд ли кому-то понравится перспектива случайно вывести систему Windows из строя, просто удалив несколько важных ключей во время отладки самостоятельно написанного кода C#, который работает с системным реестром.

После обнаружения подлежащего чтению или модификации ключа можно с помощью метода SetValue() или GetValue() , соответственно, установить либо извлечь данные из него. Оба эти метода принимают в качестве параметра строку с именем значения, но SetValue() также требуется дополнительно передать в качестве параметра ссылку на объект, который содержит детали, касающиеся значения. Поскольку по определению этот параметр должен представлять собой ссылку на объект, он на самом деле может быть ссылкой на любой класс. По типу предоставляемого класса метод SetValue() и будет определять тип для значения - REG_SZ, REG DWORD или REG_BINARY. Например:

RegistryKey hkMine = HkSoftware.CreateSubKey("MyOwnSoftware") ; hkMine.SetValue("MyStringValue", "Hello World"); hkMine.SetValue("MyIntValue", 20);

В этом коде для ключа устанавливаются два значения: MyStringValue с типом REG_SZ и MyIntValue с типом REG_DWORD.

»), в котором собраны некоторые примеры по применению вышеозначенных функций.




1. Краткое пояснение. Изначальная постановка задачи.


Была поставлена задача: создать пользовательский «MessageBox», который, кроме стандартных элементов типа «текст» и «кнопки», имел бы еще и «CheckBox», перевод которого в состояние «установлено» должен был бы приводить к тому, что это сообщение больше не будет показано.

Соответственно, эта информация должна быть сохранена в реестре. Причем в виде пары значений: «StringId» (все тексты должны быть внесены в «string table» из-за поддержки многоязычности в проекте) + «Flag» (т.е. состояние этого «CheckBox»).



Благодаря этому и появился вышеупомянутый класс для работы с реестром.


2. Общая информация.


2.1. Общий принцип построения реестра.


Реестр имеет иерархическую структуру, аналогичную каталогу (вложенные папки, деревья). Корневые элементы представляют собой установленные Майкрософтом константы.


HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS


Каждый из корневых элементов - корневых ключей - имеет подключи - папки (далее - ключи или подключи), те, в свою очередь, тоже могут иметь свои подключи и т.д. В подключе, находящемся в этой цепочке, могут содержаться параметры и соответствующие им значения. Например:


HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
IE4
Setup
Path = "%programfiles%\Internet Explorer"


В примере:

  • HKEY_LOCAL_MACHINE - корневой ключ.
  • Path - параметр;
  • все остальные - подключи.


2.2. Наши возможности.


С помощью стандартных функций мы можем:

  • считывать и запоминать имена ключей и параметров;
  • считывать и запоминать значения параметров;
  • создавать и удалять ключи;
  • получать общую информацию о ключах и их параметрах.

3. Описание функций.


3.1. Открываем и закрываем реестр.


Эти две команды - основа основ. И они самые простые в использовании. ;-)


Открываем реестр.


CRegistryManip::OpenRegKey (
const HKEY hKey,
const TCHAR* pSubKey,
HKEY& hKeyPrograms,
REGSAM samDesired = KEY_READ
);

    • HKEY_CLASSES_ROOT ,
    • HKEY_CURRENT_CONFIG ,
    • HKEY_CURRENT_USER ,
    • HKEY_LOCAL_MACHINE ,
    • HKEY_USERS ;
  • pSubKey - подраздел в реестре, который нас интересует (например: «Microsoft\IE4\Setup»);
  • hKeyPrograms - указатель на handle (описатель) открытого ключа;
  • samDesired - уровень доступа (для чтения значений, для чтения имен параметров, записи, создания ключей и т.д.):
    • KEY_ALL_ACCESS - максимальный доступ. Представляет собой комбинацию ключей: KEY_QUERY_VALUE , KEY_ENUMERATE_SUB_KEYS , KEY_NOTIFY , KEY_CREATE_SUB_KEY , KEY_CREATE_LINK и KEY_SET_VALUE ;
    • KEY_READ - для чтения информации из реестра. Представляет собой комбинацию ключей: KEY_QUERY_VALUE , KEY_ENUMERATE_SUB_KEYS и KEY_NOTIFY ;
    • KEY_WRITE - для записи информации в реестр. Представляет собой комбинацию ключей: KEY_SET_VALUE и KEY_CREATE_SUB_KEY ;
    • KEY_QUERY_VALUE - для опроса значений параметров;
    • KEY_ENUMERATE_SUB_KEYS - для чтения имен подключей;
    • KEY_NOTIFY - для изменения нотификаций;
    • KEY_CREATE_SUB_KEY - для создания подключа;
    • KEY_CREATE_LINK - для создания линка;
    • KEY_SET_VALUE - для установки значений параметров.

Чтобы открыть ключ, используем стандартную функцию RegOpenKeyEx() .


Краткое описание функции RegOpenKeyEx() .


Эта функция получает: hKey - имя корневого ключа в реестре, pSubKey - имя подключа, который мы хотим открыть и samDesired - уровень доступа к информации. В случае удачного завершения функция возвращает hKeyPrograms - указатель на открытый ключ.

Возвращаемое значение функции::RegOpenKeyEx() - тип ULONG . Значение ERROR_SUCCESS означает благополучное завершение выполнения функции, все остальное говорит о том, что нам где-то и в чем-то не повезло. ;-)





HKEY hKeyPrograms = NULL;
ULONG nRes = OpenRegKey (
HKEY_LOCAL_MACHINE,
cstrSubKey,
hKeyPrograms
);


Закрываем реестр.


(Какой-либо ключ, который был перед этим открыт с помощью OpenRegKey() .)


CRegistryManip::CloseRegKey(
HKEY hKey
);


Где hKey - тот самый указатель на handle (описатель) открытого ключа, который нам вернула функция OpenRegKey() .


Чтобы закрыть ключ используем стандартную функцию RegCloseKey() .


Краткое описание функции RegCloseKey() .


Эта функция получает hKey - указатель на открытый ключ. Она закрывает наш сеанс работы с реестром, открытый функцией RegOpenKeyEx() . Эти функции всегда должны вызываться в паре.



Вызов выглядит следующим образом:


CString cstrSubKey (_T("SOFTWARE\\Microsoft\\IE4\\Setup"));
HKEY hKeyPrograms = NULL;
BOOL bRes = OpenRegKey (
HKEY_LOCAL_MACHINE,
cstrSubKey,
hKeyPrograms
);

bRes = CloseRegKey (hKeyPrograms);


3.2. Проверяем наличие ключа в реестре.


Мы можем проверить, существует ли в реестре нужный нам ключ. Например, «HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IE4\Setup».


CRegistryManip::CheckIfKeyExists (
const HKEY hKey,
const TCHAR* pSubKey
);

  • hKey - один из корневых ключей в реестре:
    • HKEY_CLASSES_ROOT ,
    • HKEY_CURRENT_CONFIG ,
    • HKEY_CURRENT_USER ,
    • HKEY_LOCAL_MACHINE ,
    • HKEY_USERS ;
  • pSubKey - подраздел в реестре, который нас интересует (в нашем случае: «SOFTWARE\Microsoft\IE4\Setup»).

Для проверки нам достаточно вызвать функцию OpenRegKey() : если интересующий нас ключ существует, функция вернет TRUE , иначе - FALSE .

Вызов выглядит следующим образом:


CString cstrSubKey (_T("SOFTWARE\\Microsoft\\IE4\\Setup"));
BOOL bRes = OpenRegKey (
HKEY_LOCAL_MACHINE,
cstrSubKey
);


3.3. Создаем новый ключ.


Например, «HKEY_LOCAL_MACHINE\SOFTWARE\Irina».


CRegistryManip::CreateNewKey (
const HKEY hKeyBase,
const TCHAR* pKeyPath,
const TCHAR* pNewKey
);

  • hKeyBase - один из корневых ключей в реестре:
    • HKEY_CLASSES_ROOT ,
    • HKEY_CURRENT_CONFIG ,
    • HKEY_CURRENT_USER ,
    • HKEY_LOCAL_MACHINE ,
    • HKEY_USERS ;
  • pKeyPath - подраздел в реестре, который нас интересует (в нашем случае: «SOFTWARE»). Этот ключ - родитель для нашего нового ключа;
  • pNewKey - наш новый ключ (в нашем случае - «Irina»).

Чтобы создать ключ, используем стандартную функцию RegCreateKeyEx() .


Краткое описание функции RegCreateKeyEx() .


Эта функция получает hKey (имя основного ключа в реестре), pSubKeyNew = pKeyPath (имя подключа, который мы хотим открыть) + pNewKey (имя нового подключа) и samDesired (уровень доступа к информации).

В случае удачного завершения функция возвращает hKeyPrograms (указатель на созданный подключ).


В списке есть еще некоторые параметры:

  • lpClass - имя класса (Я долго искала какую-либо информацию о том, каково практическое применение этого параметра, но ничего умного не нашла... Во всех приводимых примерах этот параметр равен NULL . Я последовала примеру. ;-) Если кто-то сможет меня поправить в этом вопросе, буду премного благодарна.);
  • dwOptions - специальный флаг, который по умолчанию равен REG_OPTION_NON_VOLATILE . В обычной жизни этого хватает (Особо осложненные жизненные обстоятельства я не рассматривала, так как у меня на это просто не было времени. Но я думаю, что при необходимости всегда можно найти нужную информацию.);
  • lpSecurityAttributes - устанавливает правила для наследования (использования) полученного указателя на созданный подключ процессами - детьми основного процесса. Опять же, в обычной жизни может быть без зазрения совести равен NULL ;
  • lpdwDisposition - флаг, который говорит о том, что либо этот ключ уже существует, либо еще нет и должен быть создан. Если установить его в NULL , то система сама решает, что ей делать исходя из наличия или отсутствия заданного ключа. То есть, если ключ уже существует, функция работает как RegOpenKeyEx() , если нет - она создает заданный ключ;
  • samDesired - уровень доступа к информации в реестре. Для создания ключа должен быть установлен как минимум равным KEY_CREATE_SUB_KEY (но лучше всего - KEY_ALL_ACCESS).

Еще одно замечание: никогда не получится создать параметр непосредственно под основным ключом (HKEY_CLASSES_ROOT и т.д.). Необходимо сначала создать свой подключ и только затем создавать параметры.


Вызов выглядит следующим образом:


CString cstrSubKey (_T("SOFTWARE"));
CString cstrNewKey (_T("Irina"));
BOOL bRes = CreateNewKey (
HKEY_LOCAL_MACHINE,
cstrSubKey,
cstrNewKey
);


3.4. Удаляем подключ или параметр из реестра.


CRegistryManip::DeleteInfoFromRegistry (
const HKEY hKey,
const char* pSubKey,
const TCHAR* pKeyName
);

  • pSubKey - подраздел в реестре, который нас интересует (например: «SOFTWARE\Irina»);
  • pKeyName - имя параметра (Например, подключ «Irina» иммет параметр «StringID» со значением, равным 2000. В этом случае pKeyName равно «StringID».).

Вызов выглядит следующим образом:


BOOL bRes = FALSE;

// удаление параметра

HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Irina"),
_T("StringID")
);

// удаление подключа
bRes = DeleteInfoFromRegistry (
HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Irina"),
NULL
);


Удаляем подключ.


CRegistryManip::DeleteSubKeyFromRegistry (
const HKEY hKey,
const char* pSubKey
);


Чтобы удалить подключ, используем стандартную функцию RegDeleteKey() .


Краткое описание функции RegDeleteKey() .


Эта функция получает:

  • pSubKey - имя подключа, который мы хотим удалить.

Удаляем параметр.


CRegistryManip::DeleteParamFromRegistry (
const HKEY hKey,
const char* pSubKey,
const TCHAR* pKeyName
);


Если речь идет о подключе, то достаточно вызова стандартной функции RegDeleteKey() .

Если же надо удалить параметр, то тогда надо сначала открыть реестр, затем удалить параметр при помощи стандартной функции RegDeleteValue() , в заключение закрыть реестр.

При открытии реестра уровень доступа должен быть как минимум KEY_SET_VALUE . Для удаления параметра используем стандартную функцию RegDeleteValue() .


Краткое описание функции RegDeleteValue() .


Эта функция получает:

  • hKey - указатель на открытый ключ;
  • lpValueName - имя параметра, который мы хотим удалить.

3.5. Устанавливаем значение параметра.


Например:


HKEY_LOCAL_MACHINE\\SOFTWARE\\Irina - подключ
StringId = 2000 (StringId - это имя параметра, 2000 - его значение)


CRegistryManip::SetOneValue (
HKEY hKey,
const TCHAR* pKeyName,
const TCHAR* pKeyVal,
DWORD dwType = REG_SZ
);

  • pKeyName - имя параметра;
  • pKeyVal - значение параметра;
  • dwType - тип параметра.

Чтобы установить параметр, используем стандартную функцию RegSetValueEx() .


Краткое описание функции RegSetValueEx() .


Эта функция получает:

  • hKey - указатель на открытый ключ;
  • pKeyName - имя параметра, значение которого мы хотим установить;
  • dwType - тип данных;
  • lpData - адрес переменной (т.е. области памяти), в которую будет помещен результат (тип этой переменной зависит от типа данных);
  • cbData - размер области этой памяти.

Если тип данных - REG_SZ , то для получения результата надо создать массив типа char (или TCHAR , если мы работаем с Unicode).

Если тип данных - REG_BINARY , то для получения результата надо создать переменную типа int .

Если тип дfанных - REG_DWORD , то для получения результата надо создать переменную типа DWORD .


Применение преобразования любого из этих типов данных в (BYTE*) необходимо для получения правильного результата.



Вызов выглядит следующим образом:


CString cstrSubKey (_T("SOFTWARE\\Irina"));
CString cstrParName (_T("StringID"));
CString cstrParVal (_T("2000"));
HKEY hKeyPrograms = NULL;

// Сначала вызываем
// OpenRegKey(HKEY_LOCAL_MACHINE, cstrSubKey, hKeyPrograms),
// т.к. сначала надо открыть ключ, в котором находится
// наш параметр, затем вызываем функцию по установке
// значения параметра. В данном случае мы не передаем тип,
// т.к. он по умолчанию уже установлен как REG_SZ.

ULONG nRes = SetOneValue (
hKeyPrograms,
cstrParName,
cstrParVal
);

// В конце закрываем реестр: CloseRegKey(hKeyPrograms).


3.6. Получаем значение параметра.


CRegistryManip::getInfoFromRegistry (
const HKEY hKey,
const TCHAR* pSubKey,
const TCHAR* pRegKey,
TCHAR *pRes,
DWORD dwType = REG_SZ
);

  • hKey - один из корневых ключей в реестре: HKEY_CLASSES_ROOT и т.д.;
  • pSubKey - подраздел в реестре, который нас интересует (например, «Software\Irina»);
  • pKeyName - имя параметра (например: «StringID»);
  • pRes - значение параметра (возвращаемое этой функцией);
  • dwTyp e - тип параметра.

Сама функция осуществляет следующие действия: открывает реестр и вызывает долонительную функцию CRegistryManip::GetOneValueFromReg() , которая считывает информацию из реестра в зависимости от типа данных:


CRegistryManip::GetOneValueFromReg (
HKEY hKey,
const TCHAR* pRegKey,
TCHAR *pRes,
DWORD dwType = REG_SZ
);

  • hKey - указатель на handle (описатель) открытого ключа, который нам вернула функция OpenRegKey() ;
  • pRegKey - имя параметра (например, «StringID»);
  • pRes - значение параметра, возвращаемое этой функцией;
  • dwType - тип параметра.

Для получения значения используем стандартную функцию RegQueryValueEx() .


Краткое описание функции RegQueryValueEx() .


Эта функция получает следующие параметры:

  • hKey - указатель на открытый ключ;
  • lpValueName - имя параметра, значение которого мы хотим получить;
  • lpReserved - зарезервированное значение, равно NULL ;
  • lpType - адрес переменной (т.е. области памяти), в которую будет помещен тип результата;
  • lpData - адрес переменной, в которую будет помещен результат. В зависимости от типа данных контейнером для получения значения выступает либо строка символов, либо переменная типа int ;
  • lpcbData - адрес переменной, в которой находится размер переменной, предназначенной для помещения в нее результата.

Применение преобразования любого из этих типов данных в (BYTE*) необходимо для получения правильного результата. Вызов выглядит следующим образом (я беру пример вызова этой функции из getInfoFromRegistry()):



HKEY hKeyPrograms; // получим при вызове OpenRegKey()
TCHAR dwBuffer;
GetOneValueFromReg(hKeyPrograms, pRegKey, dwBuffer, dwType);


3.7. Получаем количество параметров.


Например:


HKEY_LOCAL_MACHINE\\SOFTWARE\\Irina - папка (подключ)
StringId -> параметр
Flag -> параметр
Param_bin -> параметр


Итого в папке 3 параметра. Наша задача - получить это количество программным путем.


CRegistryManip::GetCountOfSubKeys (
HKEY hKey,
unsigned long& nSubKeysCount
);

  • hKey - указатель на handle (описатель) открытого ключа, который нам возвращает функция OpenRegKey() ;
  • nSubKeysCount - количество параметров, возвращаемое функцией значение.

Для получения этой информации используем стандартную функцию RegQueryInfoKey() .


Краткое описание функции RegQueryInfoKey() .

  • hKey - указатель на открытый ключ в реестре, который нас интересует;
  • lpClass - адрес переменной, где находится имя класса;
  • lpcbClass - адрес переменной, в которой находится размер буфера для имени класса;
  • lpReserved - зарезервированный параметр, равен NULL ;
  • lpcSubKeys - адрес переменной, в которой находится результат - количество подключей;
  • lpcbMaxSubKeyLen - адрес переменной, в которой находится длина для имени подключа;
  • lpcbMaxClassLen - адрес переменной, в которой находится длина буфера, предназначенного для хранения имени класса;
  • lpcValues - адрес переменной, в которой находится еще один результат - количество параметров в данном ключе;
  • lpcbMaxValueNameLen - адрес переменной, в которой находится размер буфера для имени параметра или подключа;
  • lpcbMaxValueLen - адрес переменной, в которой находится размер буфера для значения параметра;
  • lpcbSecurityDescriptor - адрес переменной, в которой может находиться security-информация;
  • lpftLastWriteTime - адрес переменной типа FILETIME , в которой находится время последнего изменения этого ключа.