Статьи

Грамотно работаем с реестром

Часть 3. Работа с реестром.

Теперь мы подходим к самому главному: работе с реестром. Реестр в Windows служит хранилищем всех настроек. Любое неадекватное вмешательство может привести к краху всей системы. Поэтому, если Вы не выполнили указаний, данных в самом начале статьи – сейчас самое время их сделать.

Остановимся чуть подробнее на структуре реестра. 2 основных его преимущества: сохранение всей информации в едином месте и иерархическая структура. Начнем с "самого верха". Здесь имеется 6 основных разделов (ключей):

Каждый из них отвечает за "свой" раздел работы. HKEY_CLASSES_ROOT – содержит данные, связывающие типы файлов (по расширениям) с приложениями, работающими с ними. HKEY_CURRENT_USER – содержит данные, которые описывают профиль пользователя, т.е. внешний вид и поведение рабочего стола, данные различных программ, сетевые соединения. Именно здесь и сохраняются все основные настройки приложений, используемых в Windows, в том числе и VB. HKEY_LOCAL_MACHINE – здесь хранятся настройки компьютера, общие для всех зарегистрированных пользователей. HKEY_USERS – этот раздел хранит информацию о профилях каждого из зарегистрированных пользователей. HKEY_CURRENT_CONFIG – включает в себя информацию о шрифтах, зарегистрированных на данном компьютере, а так же данные о принтерах. HKEY_DYN_DATA – самый часто обновляемый раздел реестра, т.к. включает в себя часто изменяющиеся динамические данные.

Visual Basic не имеет встроенных функций для работы с любой частью реестра. Тот небольшой участок реестра, к которому допуск из VB напрямую разрешен, был подробно описан в первой части данной статьи. Однако существует "палочка-выручалочка" – это API-функции. Задекларировав их вначале, из программы можно обратиться в любой момент к любому разделу реестра. Перечень функций для работы с реестром (все они начинаются с Reg), а так же константы приведены в листинге.

Итак, основные функции и что они выполняют:

API-функция

Описание

RegCloseKey

Освобождает манипулятор раздела

RegCreateKeyEx

Создает раздел, а если раздел существует, то просто открывает его. Это очень удобно, когда неизвестно: существует данный раздел реестра или нет.

RegDeleteKey

Удаляет раздел со всеми входящими в него подразделами

RegDeleteValue

Удаляет заданный параметр из конкретного раздела

RegEnumKeyEx

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

RegEnumValue

Аналогична предыдущей функции, с той лишь разницей, что возвращает параметр из конкретного раздела.

RegOpenKeyEx

Открывает заданный раздел

RegQueryValueEx

Получает информацию о типе и данные для параметра с заданным именем.

RegSetValueEx

Сохраняет данные в параметре реестра.

Проверять все производимые нами изменения можно через редактор реестра. Обычно он располагается в директории Windows (файл regedit.exe). Не забудьте, что после проведенных изменений в реестре, чтобы эти изменения увидеть, редактор необходимо обновить (клавиша F5). Для наших примеров мы будем использовать стандартную ветку реестра: HKEY_CURRENT_USER\SOFTWARE\VB AND VBA PROGRAM SETTINGS. А когда Вы поймете суть работы функций, то заменить пути сохранения в реестре необходимых Вам данных не составит труда.

Создание раздела.

Создадим новый подраздел TestRegistry в вышеуказанной ветке. Расположим на форме кнопку Command1. В Form_Load инициализируем наши переменные, отвечающие за путь в реестре.

Private Create As Long

Private SubKey As String

Private hKey As Long

Private Sub Form_Load()

  SubKey = "SOFTWARE\VB AND VBA PROGRAM SETTINGS"

  hKey = HKEY_CURRENT_USER

End Sub

Примечание: для значения переменной hKey берется константа, объявленная в модуле.

В обработке события кнопки попросим пользователя ввести Имя Подраздела. Затем проследим, чтобы перед названием стоял знак "\". И, наконец, проверим функцию, создающую новый подраздел.

Private Sub Command1_Click()

    On Error GoTo ErrorRoutineErr:

    Dim Reply As String

    Reply = InputBox("Введите имя для создания подраздела:" & vbCrLf & _
                 "в разделе " & SubKey)

    If Reply = "" Then

        Exit Sub

    End If

    

    If Mid(Reply, 1, 1) <> "\" Then

        Reply = "\" & Reply

    End If

    

    If Reply = "" Then

        MsgBox "Не могу создать подраздел."

        Exit Sub

    End If

    

    If CreateRegKey(Reply) Then

        MsgBox "Создан новый подраздел"

    Else

        MsgBox "Не могу создать подраздел."

    End If

    Exit Sub

 

ErrorRoutineErr:

  MsgBox "Ошибка: <" & Err.Number & "> - " & Err.Description, _
    vbExclamation + vbOKOnly, "Созданиие подраздела"

End Sub

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

Function CreateRegKey(NewSubKey As String) As Boolean

    On Error GoTo ErrorRoutineErr:

    Dim phkResult As Long

    Dim SA As SECURITY_ATTRIBUTES

    

    CreateRegKey = (RegCreateKeyEx(hKey, SubKey & NewSubKey, _
      0, "", REG_OPTION_NON_VOLATILE, _
       KEY_ALL_ACCESS, SA, phkResult, Create) = ERROR_SUCCESS)

    

    RegCloseKey phkResult

    Exit Function

    

ErrorRoutineErr:

  MsgBox "Ошибка: <" & Err.Number & "> - " & Err.Description, _
    vbExclamation + vbOKOnly, "Созданиие подраздела"

    CreateRegKey = False

  

End Function

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

Создание параметра.

После того, как раздел или подраздел создан, необходимо в нем создать параметр и присвоить ему значение. Допустим, в предыдущем шаге мы создали подраздел "TestRegistry". Теперь внесем имя параметра "Test1" и его значение "New Value". Для этого нам понадобится все та же форма и вторая кнопка на ней Command2. Инициализация переменных у нас уже описана выше, в предыдущем шаге. Добавим обработку нажатия на вторую кнопку. Запросим у пользователя сначала имя параметра, а затем его значение. И если все ОК – то сделаем запись.

Private Sub Command2_Click()

    Dim Reply1 As String, Reply2 As String

    SubKey = SubKey & "\TestRegistry"

 

    Reply1 = InputBox("Введите имя параметра:" & _
        vbCrLf & "в разделе: " & SubKey)

    If Reply1 = "" Then

        Exit Sub

    End If

    

    Reply2 = InputBox("Введите значение параметра:" & vbCrLf _
        & "в разделе: " & SubKey & vbCrLf & "для параметра: " & Reply1)

    If Reply2 = "" Then

        Exit Sub

    End If

    

    If Not SetRegValue(hKey, SubKey, Reply1, Reply2) Then

        MsgBox "Не могу создать параметр."

    End If

End Sub

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

Function SetRegValue(hKey As Long, sSubKey As String, _
                    ByVal sSetValue As String, _
                    ByVal sValue As String) As Boolean

    On Error GoTo ErrorRoutineErr:

    Dim phkResult As Long

    Dim lResult As Long

    Dim SA As SECURITY_ATTRIBUTES

    

    RegCreateKeyEx hKey, sSubKey, 0, "", _
        REG_OPTION_NON_VOLATILE, _
        KEY_ALL_ACCESS, SA, phkResult, Create

    lResult = RegSetValueEx(phkResult, sSetValue, 0, _
        REG_SZ, sValue, CLng(Len(sValue) + 1))

    RegCloseKey phkResult

    SetRegValue = (lResult = ERROR_SUCCESS)

    Exit Function

ErrorRoutineErr:

  MsgBox "Ошибка: <" & Err.Number & "> - " & Err.Description, _
    vbExclamation + vbOKOnly, "Созданиие параметра"

  SetRegValue = False

End Function

Удалить параметр.

Итак, у нас создан подраздел "TestRegistry", а в нем параметр "Test1". Располагаем на форме третью кнопку – Command3. Как и во всех предыдущих наших манипуляциях, вначале мы должны открыть раздел, а по окончании работы закрыть его, освободив манипулятор. Удаление параметра производится с помощью API-функции RegDeleteValue.

Private Sub Command3_Click()

    Dim phkResult As Long

    Dim SA As SECURITY_ATTRIBUTES

    SubKey = "SOFTWARE\VB AND VBA PROGRAM SETTINGS\TestRegistry"

    RegCreateKeyEx hKey, SubKey, _
        0, "", REG_OPTION_NON_VOLATILE, _
   
    KEY_ALL_ACCESS, SA, phkResult, Create

    If RegDeleteValue(phkResult, "Test1") = ERROR_SUCCESS Then

        MsgBox "Параметр удален"

    Else

        MsgBox "Не могу удалить параметр"

    End If

    RegCloseKey phkResult

End Sub

 

Удалить раздел.

В принципе, все различия между удалением параметра и удалением раздела (подраздела), заключаются только в использовании другой API-функции: RegDeleteKey. Все остальное – идентично. Размещаем на форме четвертую кнопку и удаляем раздел "TestRegistry".

Private Sub Command4_Click()

    Dim phkResult As Long

    Dim SA As SECURITY_ATTRIBUTES

    SubKey = "SOFTWARE\VB AND VBA PROGRAM SETTINGS"

    

    RegCreateKeyEx hKey, SubKey, 0, _
        "", REG_OPTION_NON_VOLATILE, _
        KEY_ALL_ACCESS, SA, phkResult, Create

    If RegDeleteKey(phkResult, "TestRegistry") = ERROR_SUCCESS Then

        MsgBox "Подраздел удален"

    Else

        RegCloseKey phkResult

        MsgBox "Не могу удалить подраздел"

    End If

End Sub

Получение значения раздела.

В связи с тем, что мы удалили в предыдущей работе наш подраздел и его содержимое, давайте сначала восстановим удаленные параметры: Запустим на выполнение сначала первую кнопку, а затем вторую. Проверим через Regedit. У нас должно получиться: подраздел "TestRegistry", а в нем параметр "Test1" со значением "New Value".

Добавим очередную кнопку Command5.

Private Sub Command5_Click()

  SubKey = "SOFTWARE\VB AND VBA PROGRAM SETTINGS\TestRegistry"

  MsgBox GetValue(hKey, SubKey, "Test1", "Ничего нет")

End Sub

Теперь займемся написанием самой функции. Как всегда, вначале открываем раздел, а в конце не забудем освободить манипулятор раздела. С помощью API-функции RegQueryValueEx получаем значение параметра. Полученный результат возвращаем функции, а в случае его не нахождения – присваиваем значение sDefault.

Обратите внимание, что сама функция возвращает тип Variant, т.к. значение параметра может быть не только строковым числом.

Function GetValue(hKey As Long, sSubKey As String, _
    sKey As String, sDefault As String) As Variant

    On Error GoTo ErrorRoutineErr:

    Dim phkResult As Long

    Dim lResult As Long

    Dim sBuffer As String

    Dim lBuffSize As Long

    'Создаем буфер

    sBuffer = Space(255)

    lBuffSize = Len(sBuffer)

    RegOpenKeyEx hKey, sSubKey, 0, 1, phkResult

    lResult = RegQueryValueEx(phkResult, sKey, 0, _
        0, sBuffer, lBuffSize)

    RegCloseKey phkResult

    If lResult = ERROR_SUCCESS Then

        GetValue = Left(sBuffer, lBuffSize - 1)

    Else

        GetValue = sDefault

    End If

    Exit Function

    

ErrorRoutineErr:

  MsgBox "Ошибка: <" & Err.Number & "> - " & Err.Description, _
    vbExclamation
+ vbOKOnly, "Получение параметра"

    GetValue = ""

End Function

Получение всех подразделов конкретного раздела и получение всех значений раздела.

 Подробно изучив выше перечисленные функции и процедуры, Вы, при необходимости, можете их использовать для получения названий подразделов или значений всех параметров подраздела. Собирать эти названия можно в массив или, например, напрямую – в ListBox. Перебор параметров осуществляется с помощью цикла Do … Loop (или While … Wend кому как привычнее), до тех пор пока искомое значение равно ERROR_SUCCESS.

Разобравшись со всеми функциями, Вы можете использовать представленный Листинг, как отдельный модуль, или преобразовать его в отдельный класс.

Обратите внимание: в представленном листинге функции отображены в несколько ином виде – более глобальном.

2001 г.

К статьям Листинг Часть 4
Hosted by uCoz