Часть 3. Работа с реестром.
Теперь мы подходим к самому главному: работе с реестром. Реестр в Windows служит хранилищем всех настроек. Любое неадекватное вмешательство может привести к краху всей системы. Поэтому, если Вы не выполнили указаний, данных в самом начале статьи – сейчас самое время их сделать.
Остановимся чуть подробнее на структуре реестра. 2 основных его преимущества: сохранение всей информации в едином месте и иерархическая структура. Начнем с "самого верха". Здесь имеется 6 основных разделов (ключей):
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIG
HKEY_DYN_DATA
Каждый из них отвечает за "свой" раздел работы. 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 |