Страницы

11 апреля 2012 г.

C++. Работа с реестром Windows. Создание собственного класса.

       Доброго времени суток. Рад видеть Вас в своем блоге.
       Сегодня хотелось бы обсудить работу с реестром Windows. Да, эта тема далеко не новая, информации по ней в интернете куча. НО, я решил подойти к вопросу как новичок. Новичок, т.к. с недавнего времени заинтересовался C++ и на данном этапе стараюсь впитать как можно больше полезной и качественной инфы, чтобы пользоваться возможностями этого языка наиболее оптимально. Соответственно, касаемо работы с реестром "голый" Windows API я никогда не использовал.
       Вернемся к реестру... Я буду рассматривать работу с реестром Windows средствами Windows API. Возможно есть и другие способы, но я их не рассматривал.
       Как человек, несколько лет просидевший на паскале, я конечно же не мог не написать свой класс который будет иметь менее обширный интерфейс нежели голый API интерфейс описанных ниже функций. Об этом позже...


Итак, функции для работы с реестром:

ВНИМАНИЕ!
Ниже я опишу не все функции, а лишь те которые использовал для написания своего класса. Подробное описание всех функций можно найти тут: Программирование для системного реестра на C++

Создание раздела в реестре:
LONG RegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved,
LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
LPDWORD lpdwDisposition)

Функция создает раздел если его нет, и открывает если уже он существует.

Функция для открытия существующего раздела реестра:
LONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions,
REGSAM samDesired, PHKEY phkResult)

Функция для закрытия описателя реестра:
LONG RegCloseKey(HKEY hKey);
Функция устанавливающая значение параметра реестра:
LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData)

Функция возвращающая информацию о параметре и значение параметра:
LONG RegQueryValueEx(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)

       В статье, ссылку на которую я привел выше, нет описания типов значений (DWORD dwType и LPDWORD lpType) которые используются в функциях RegSetValueEx и RegQueryValueEx. Поэтому добавлю описание этих типов сюда:

REG_BINARY
Это бинарный (или двоичный) тип. То есть сюда входят только две цифры – 1 и 0. Он не очень привычен для нас, но для компьютера типа лучшего, чем этот, просто не найти…

REG_DWORD
Это целочисленный тип. Многие параметры служб и драйверов устройств имеют этот тип и отображаются в двоичном, шестнадцатеричном или десятичном форматах.

REG_EXPAND_SZ
Строковый тип.

REG_MULTI_SZ
Тип, похожий на предыдущий. Но это не одна строка, а набор строк.

REG_SZ
Тоже строковый тип, но в отличие от REG_EXPAND_SZ это строка фиксированной длины.

       Это перечень тех функций которые мне пригодились для написания собственного класса "Registry".

Класс Registry.

Класс имеет следующую интерфейсную часть (h-файл):

namespace win_reg {
class Registry {
private:
 bool pr_is_error;
 HKEY pr_hkey;
 DWORD pr_reserved;
 REGSAM pr_desired;
 DWORD pr_options;
 DWORD pr_type;
 DWORD pr_buffer_size;
 std::string pr_buffer_str;

 //в этом методе вызывается API функция возвращающая значение
 void SysGetValue(LPCTSTR a_parname, BYTE* a_buffer, DWORD* a_buf_size);
 //в этом методе вызывается API функция устанавливающая значение
 void SysSetValue(LPCTSTR a_parname, DWORD a_type, const BYTE* a_value, DWORD a_value_size);

public:
 Registry();
 ~Registry();

 //Создаем/открываем ключ в зависимости от значения параметра bool a_can_create
 void OpenKey(HKEY* a_hkey, LPCTSTR a_subkey, bool a_can_create);

 //методы установки значений
 void SetValueString(LPCTSTR a_parname, const TCHAR* a_value);
 void SetValueExpandString(LPCTSTR a_parname, const TCHAR* a_value);
 void SetValueInt(LPCTSTR a_parname, const long* a_value);
 void SetValueFloat(LPCTSTR a_parname, const double* a_value);

 //методы возврата значений
 std::string GetValueString(LPCTSTR a_parname);
 std::string GetValueExpandString(LPCTSTR a_parname);
 long GetValueInt(LPCTSTR a_parname);
 double GetValueFloat(LPCTSTR a_parname);

 //методы закрывающие описатель реестра
 void CloseKey(HKEY a_hkey);
 void CloseKey();
};


} //end namespace


       Интерфейс частично схож с тем который предоставляет паскалевский модуль registry. Думаю интерфейс понятен и в дополнительных разъяснениях не нуждается. :)

Пример использования объекта класса:

int main()
{
 HKEY hkey = HKEY_LOCAL_MACHINE;
 LPCTSTR SubKey = TEXT("Software\\Test_DM");
 LPCTSTR ParName = TEXT("TestParameter");

 //создание объекта
 win_reg::Registry r_test;

 //Открываем ключ (с параметром false т.к. уверенны что он существует)
 r_test.OpenKey(&hkey, SubKey, false);

 //возвращаем строковое значение параметра "TestParameter"
 std::string ttt;
 ttt = r_test.GetValueString(ParName);
 //cout--ttt--endl;

 //перезаписываем значение изменяя заодно и его тип
 TCHAR* WrStr;
 WrStr = "Hello Holywood!!! * New Value";
 r_test.SetValueExpandString(ParName, WrStr);
 ttt = r_test.GetValueExpandString(ParName);
 //cout--ttt--endl;

 //создаем параметр типа int (записываем в него значение "10101" и тут же выводим)
 ParName = TEXT("TestParameter_int");
 long tint;
 tint = 10101;
 r_test.SetValueInt(ParName, &tint);
 long res;
 res = r_test.GetValueInt(ParName);
 //cout--res--endl;

 //создаем параметр типа double (записываем в него значение "1231.22" и тут же выводим)
 ParName = TEXT("TestParameter_double");
 double dint;
 dint = 231.22;
 r_test.SetValueFloat(ParName, &dint);
 double dres;
 dres = r_test.GetValueFloat(ParName);
 //cout--dres--endl;

 r_test.CloseKey(hkey);


 return 0;
}

       Класс не реализовывает всех возможностей которые предоставляет Windows API, но это до тех пор пока не возникла необходимость в расширении функционала. А пока в нем есть все "инструменты" первой необходимости. :)



Если кому интересно, исходники класса и примеров применения можно скачать тут:

Download Source

(Исходники 100% компилятся на gcc и на VS 2005/2008)

Комментариев нет:

Отправить комментарий