编程解决注册表问题所需的函数详解

在各种程序设计语言当中,Visual Basic 是最容易上手的了。我本人就是从QBASIC 语言直接转移过来的。我曾经做过一个实验:将原先在QBASIC 语言中编写的代码,原封不动的移植到VB上来,居然有多数能够运行。其他的代码也基本上只作微量调整(如把QBASIC中的“INPUT”语句统一换成VB中的“InputBox”),就可以在VB中直接使用了。另外,考虑到各种语言之间的相通性,这里以VB编程为主,对VC,Delphi,VFP只在后面给出几个实例,敬请高手指教。

  ● 使用 Visual Basic 来操作注册表

  在VB中处理注册表,通常有两种途径:一是利用VB自身的函数;二是调用 Windows API 函数来操作注册表。

  一、 MicroSoft Visual Basic 中对于注册表的操作函数

  说明:在 Visual Basic 6.0 内部,为了存储创建于 VB 的应用程序的程序信息,已经提供了一个标准的注册位置(如图1):HKEY_CURRENT_USER\Software\VB and VBA Program settings\(为了叙述简单,以下将这一位置简称“标准位置”)。





  MicroSoft Visual Basic 中对于注册表的操作函数共有4个,它们是 SaveSetting, GetSetting, GetAllSettings, DeleteSettings等。

  1、SaveSetting 在 Windows 注册表中保存或建立应用程序项目

  语法 SaveSetting appname, section, key, setting

  参数 appname:字符串表达式,包含应用程序或工程的名称,是标准位置下的一个子键。

  section:字符串表达式,包含区域名称,是 appname 下的一个子键。

  key:字符串表达式,标准位置\appname\section子键的键名(Value Name)。

  setting:字符串表达式,包含 key 的设置值。 www.xker.com()

  函数示例 下列示例先使用 SaveSetting 语句,来建立Windows标准位置(或 16位 Windows 平台的 ini 文件)里 “我的工程”应用程序的项目,然后使用 DeleteSetting 语句将之删除。因为没有指定 key参数,整个子键都会被删除掉,包括子键名称及其所有的键值(key)。

  ’ 在标准位置中添加一些设置值。

  SaveSetting appname := “我的工程”, section := “我的子键”, key := “Top”, setting := 75

  SaveSetting “我的工程”,”我的子键”, “Left”, 50

  ’ 删除子键及所有的设置值。

  DeleteSetting “我的工程”, “我的子键” ①在注册表中添加一些设置值。用 SaveSetting 语句在标准位置下建立名为“我的工程\我的子键”的子键。

  SaveSetting appname := “我的工程”, section := “我的子键”, key := “Top”, setting := 75

  SaveSetting “我的工程”, “我的子键”, “Left”, 50

  ②删除子键及所有的设置值。

  DeleteSetting “我的工程”, “我的子键”

  2、GetSetting 从 Windows 注册表中的应用程序项目返回注册表项设置值

  语法 GetSetting appname, section, key[, default]

  参数 appname:字符串表达式,包含应用程序或工程的名称。

  section:字符串表达式,包含区域名称,要求该区域有注册表项设置。

  key:字符串表达式,返回注册表项设置的名称。

  default:可选。表达式,如果注册表项设置中没有设置值,则返回缺省值。如果省略,则 default 取值为长度为零的字符串 (“”)。

  说明 如果 GetSetting 无参数,则 GetSetting 返回 default 的值

  函数示例 使用 SaveSetting 语句建立 appname 应用程序的项目,然后使用 GetSetting 函数得到其中一项设置并显示出来。因为有传入参数 default,GetSetting 函数一定会有返回值。请注意,section 名称不能用 GetSetting 函数取得。最后,使用 DeleteSetting 语句将该应用程序项删除。

  ①定义保存 GetSetting 函数返回之二维数组数据的变量

    Dim MySettings As Variant

  ②在注册表中添加项目

  SaveSetting “我的工程”,”我的子键”, “Top”, 75

  SaveSetting “我的工程”,”我的子键”, “Left”, 50

  Debug.Print GetSetting(appname := “我的工程”, section := “我的子键”, key := “Left”, default := “25”)

  ③删除注册表中项目

  DeleteSetting “我的工程”, “我的子键”
3、GetAllSettings 从 Windows 注册表中返回应用程序项目的所有注册表项设置及其相应值

  语法 GetAllSettings(appname, section)

  参数 appname 必要。字符串表达式,应用程序或工程的名称。

#p#副标题#e#

  section 必要。字符串表达式,包含区域名称,并要求该区域有注册表项设置。GetAllSettings 返回 Variant,其内容为字符串的二维数组,该二维数组包含指定区域中的所有注册表项设置及其对应值。

  说明 如果 appname 或 section 不存在,则 GetAllSettings 返回未初始化的 Varian

  函数示例 本示例首先使用 SaveSetting 语句来建立 Windows标准位置里 appname 应用程序的项目,然后再使用 GetAllSettings 函数来取得设置值并显示出来。请注意,应用程序名和 section 名称不能用 GetAllSettings 函数取得。最后,使用 DeleteSetting 语句将该应用程序项删除。

  ’ 用来保存 GetAllSettings 函数所返回之二维数组数据的变量

  ’ 整型数是用来计数用。

  Dim MySettings As Variant, intSettings As Integer

  ’ 在注册表中添加设置值。

  SaveSetting appname := “我的工程”, section := “我的子键”, key := “Top”, setting := 75

  SaveSetting “我的工程”,”我的子键”, “Left”, 50

  ’ 取得输入项的设置值。





MySettings = GetAllSettings(appname := “我的工程”,
       section := “我的子键”)
For intSettings = LBound(MySettings, 1) To
       UBound(MySettings, 1)
Debug.Print MySettings(intSettings, 0), MySettings(intSettings, 1)
Next intSettings
DeleteSetting “我的工程”, “我的子键”

  4、DeleteSetting 从应用程序项目里删除区域或注册表项设置

  语法 DeleteSetting appname, section[, key]

  参数 appname 必需的。字符串表达式,应用程序或工程的名称。

  section 必要。字符串表达式,包含要删除注册表项设置的区域名称。如果只有 appname 和 section,则将指定的区域连同所有有关的注册表项设置都删除。

  key 可选。字符串表达式,包含要删除的注册表项设置。

  说明 如果提供了所有参数,则删除指定的注册表项设置。如果试图使用不存在的区域或注册表项设置上的 DeleteSetting 语句,则发生一个运行时错误。

  函数示例 见SaveSetting函数示例

  二、 调用 Windows API 函数来操作注册表

  虽然VB本身提供了四个关于注册表的函数,但是这四个函数只能在标准位置即“HKEY_CURRENT_USER\Software\VB and VBA ProgramSettings”下读取、删除、修改键值。对于一般的应用程序,利用它们就可以达到您的目的,对于特殊的要求利用它们就显得无能为力了。在 Visual Basic 中除了使用这四个内部语句或函数外,还可以调用 Windows API 函数来操作注册表。

  所谓 API(Application Programing Interface) 是 Windows 提供的一个32位环境下的应用程序编程接口,其中包括了众多的函数,提供了相当丰富的功能。我们在编制应用程序时,可以调用其中的注册表函数来对注册表进行操作以实现我们需要的功能。Windows API 中可用于注册表的函数一共有二十多个,根据其功能不同可以分为如下几类:

  1.键管理类

   RegCloseKey() RegCreateKey() RegCreateKeyEx() RegDeleteKey() RegDeleteKeyEx() RegOpenKey() RegOpenKeyEx()

  2.值管理类

   RegDeleteValue() RegQueryValue() RegQueryValueEx() RegSetValue() RegSetValueEx()

  3.查询计数类

   RegQueryInfoKey() RegEnumKey() RegEnumKeyEx() RegEnumValue()

  4.备份/恢复类

   RegLoadKey() RegReplaceKey() RegRestoreKey() RegSaveKey()

  5.实用类

   RegConnectRegistry() RegNotifyChangeKeyValue() RegUnloadKey()

  6.安全类(仅适用于NT)

   RegGetKeySecurity() RegSetKeySecurity()

  下面详细介绍这几个Windows API 函数的用法:

  1. RegOpenKey——取得SubKey的Hkey

#p#副标题#e#

    RegOpenKeyEx():同RegOpenKey()

  VB声明 Declare Function RegOpenKey Lib “advapi32.dll” Alias “RegOpenKeyA” (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long

  参数类型及说明:

  hKey:Key Handle

  lpSubKey:SubKey名称或路径

  phkResult:若RegOpenKey执行成功,则这一参数返回Subkey的hKey.

  返回值: =0,表示成功;≠0,表示失败。[注意这一点与别的API函数不太一样]

  示例:





ret = RegOpenKey(HKEY_LOCAL_MACHINE,
         “SOFTWARE\Microsoft”, hKey)

  2.RegCreateKeyEx、RegCreateKey函数:建立SubKey

 



VB声明 Declare Function RegCreateKey Lib “advapi32.dll” Alias “RegCreateKeyA” (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
 
  它的参数用法与RegOpenKey一样。所不同的是RegOpenKey只能打开已经有的SubKey,而RegCreateKey则可以建立SubKey,比较特别的是,如果调用RegCreateKey所建立的SubKey是一个已经存在的SubKey,则它的功能和RegOpenKey相同。由于RegCreateKey的这种特性,有的程序员干脆不用RegOpenKey,而用RegCreateKey来统一代替RegOpenKey。

  示例:





ret = RegCreateKey(HKEY_LOCAL_MACHINE, “SOFTWARE\Hongqt”, hKey)

  3.RegClose函数:关闭SubKey

  



Declare Function RegCloseKey Lib “advapi32.dll”
            (ByVal hKey As Long) As Long

  当我们不再存取Registry时,将打开或建立的SubKey关闭是一个比较好的习惯,就正如我们在使用C语言的文件打开函数后必须要关闭一样。

  示例:





ret = RegOpenKey(HKEY_LOCAL_MACHINE, “SOFTWARE\Microsoft”, hKey)
……
RegClose hkey
4.RegQueryValue——读取某Key的默认值(default value)

  VB声明





Declare Function RegQueryValue Lib “advapi32.dll” Alias “RegQueryValueA” (ByVal hKey As Long, ByVal lpSubKey As String, ByVal lpValue As String, lpcbValue As Long) As Long
hKey: Key Handle

   lpSubKey:SubKey名称路径

   lpValue:返回读取的Default Value

   lpcbValue:传入lpValue参数的长度,若成功读取了默认值default value,则返回default value字符串的长度(含chr(0))这个和C语言中字符串的处理相似,都是以chr(0)作为结束符。

   返回值: =0,表示成功;≠0,表示失败。

   示例:





ret = RegQueryValue(hKey, Subkey, “”, lenS)

  5.RegSetValue——删除某Key的默认值(default value)

  VB声明





Declare Function RegSetValue Lib “advapi32.dll” Alias “RegSetValueA” (ByVal hKey As Long, ByVal lpSubKey As String, ByVal dwType As Long, ByVal lpData As String, ByVal cbData As Long) As Long

   hKey:Key Handle

   lpSubKey:Subkey名称或路径

   dwType:数据类型,但在这里只能接受REG_SZ[字符串类型]

   lpData:所设置的字符串

   cbData:lpData字符串的长度,这一长度包括chr(0)字符。

   关于dwType的可能取值

    Enum ValueType

    REG_NONE = 0

    REG_SZ = 1

    REG_EXPAND_SZ = 2

    REG_BINARY = 3

    REG_DWORD = 4

    REG_DWORD_BIG_ENDIAN = 5

    REG_MULTI_SZ = 7

    End Enum

  示例:





Function SetDefaultValue(ByVal hKey As Long, ByVal Subkey As String, ByVal Value As String) As Boolean
Dim ret As Long, lenS As Long, S As String
ret = RegSetValue(hKey, Subkey, REG_SZ, Value, LenB(StrConv(Value, vbFromUnicode)) + 1) SetDefaultValue = (ret = 0)
End Function

  6.RegQueryValueEx——读取某Key的特定名称的值(Value)

#p#副标题#e#

  VB声明和参数解释:





Declare Function RegQueryValueEx Lib “advapi32.dll” Alias “RegQueryValueExA” (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long

  hkey:Key Handle

  lpValueName:Value Name

  lpReserved:保留参数,调用时设置为0即可

  lpType:返回读取的数据类型

  lpData:返回读取的数据

  lpcbData:传入lpData数据的长度,若成功读取数据,则返回所读取的数据的长度。

   返回值: =0,表示成功;≠0,表示失败。

  说明:

  ① 这一函数除了可读取指定名称的值之外,也可以读取default value。如果要读取default value,只需要将参数lpValueName设置为””[空字符串]即可。

  ②lpType 的可能取值

  Enum ValueType

  REG_NONE = 0

  REG_SZ = 1 ——>字符串

  REG_EXPAND_SZ = 2 ——>可展开式字符串

  REG_BINARY = 3 ——>Binary数据

  REG_DWORD = 4 ——>长整数

  REG_DWORD_BIG_ENDIAN = 5 ——>BIG_ENDIAN长整数

  REG_MULTI_SZ = 7 ——>多重字符串

  End Enum

  示例:





Dim hKey As Long, ret As Long, lenData As Long, typeData As Long
Dim Name As String
‘读取HKEY_LOCAL_MACHINE\Software\Microsoft
‘\Windows\CurrentVersion\Run的internat.exe的value.
Name=”internat.exe”
ret=RegOpenKey(HKEY_LOCAL_MACHINE,
   ”Software\Microsoft\Windows\CurrentVersion\Run”, hKey)
if ret=0 then
ret = RegQueryValueEx(hKey, Name, 0, typeData,
   ByVal vbNullString, lenData)’注意ByVal千万别忘了
end if
7.RegEnumValue——列出某Key的所有名称的值





Declare Function RegEnumValue Lib “advapi32.dll” Alias “RegEnumValueA” (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, lpReserved As Long, lpType As Long, lpData As Byte, lpcbData As Long) As Long

   参数说明:

    hKey:Key Handle

    dwIndex:欲读取之名称的顺序

    lpValueName:返回所读取的名称

    lpcbValueName:传入lpValueName参数的长度,返回所读取的名称的长度,注意这一长度不含chr(0)

    lpReserved:保留参数,实际使用时传入ByVal 0即可

    lpType:返回所读取的数据类型

    lpData:返回所读取的数据

    lpcbData:传入lpData,返回所读取的数据长度

    返回值: =0,表示成功;≠0,表示失败。

  示例:





ret=0
myindex=0
while ret=0
ret=RegEnumValue(hkey,myindex,Name,ByVal 0, typeData, ByVal vbNullString, lenData)
myindex=myindex+1
wend

  8.RegSetValueEx——设置某Key特定名称的值(Value)





Declare Function RegSetValueEx Lib “advapi32.dll” Alias “RegSetValueExA” (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpData As Any, ByVal cbData As Long) As Long

  参数:

   hKey:Key Handle

   lpValueName:Value名称

   Reserved:保留参数,具体使用时置为0即可

   dwType:数据类型

   lpData:所设置的数据,注意这一参数被定义成lpData As Any,所以要传入字符串数据时别忘了在参数前加保留字ByVal

   cbData:数据的长度。注意:如果写入的数据属于REG_SZ、REG_EXPAND_SZ、REG_MULTI_SZ类型时,则这个长度应该包含chr(0)字符。

   返回值: =0,表示成功;≠0,表示失败。

  示例:





Dim hKey As Long
Dim L As Long
L = 99999
RegCreateKey HKEY_CURRENT_USER, “Software\SetValue”, hKey
RegSetValueEx hKey, “LongData”, 0, REG_DWORD, L, 4

  9.RegDeleteValue——删除某Key的某一名称

#p#副标题#e#





Declare Function RegDeleteValue Lib “advapi32.dll” Alias “RegDeleteValueA” (ByVal hKey As Long, ByVal lpValueName As String) As Long

  参数:

   hKey:Key Handle

   lpValueName: Value名称,如果想删除默认值的话,传入””[空字符串]即可。

   返回值: =0,表示成功;≠0,表示失败。

  示例:

   



‘我们假设在HKEY_CURRENT_USER\Software\SetValue有:
‘预设值——VB操作注册表
‘str1——我爱我的祖国
‘我们要删除这两个Value
ret = RegOpenKey(HKEY_CURRENT_USER, “Software\SetValue”, hKey)
If ret = 0 Then
RegDeleteValue hKey, “Str1”
MsgBox “已删除HKCU\Software\SetValueSubKeyStr1Value”
RegDeleteValue hKey, “”
MsgBox “已删除HKCU\Software\SetValueSubKey‘预设值’”
End If
 10.RegEnumKey——列出某Key的所有SubKey

  RegEnumKeyEx():返回注册表键及其子键的详细信息。





Declare Function RegEnumKey Lib “advapi32.dll” Alias “RegEnumKeyA” (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, ByVal cbName As Long) As Long

  参数说明:

   hKey:Key Handle

   dwIndex:欲读取的SubKey的顺序

   lpName:返回所读取的SubKey的名称

   cbName:传入lpName的字符串长度。

   返回值: =0,表示成功;≠0,表示失败。

  示例:





Dim hKey As Long, ret As Long, Name As String, Idx As Long
List1.Clear
Idx = 0
Name = String(256, Chr(0))
Do
ret = RegEnumKey(HKEY_CURRENT_USER, Idx, Name, Len(Name))
If ret = 0 Then
List1.AddItem Left(Name, InStr(Name, Chr(0)) – 1)
Idx = Idx + 1
End If
Loop Until ret <> 0

  11.RegDeleteKey——删除Key或者SubKey





RegDeleteKeyEx():同RegDeleteKeyEx()
Declare Function RegDeleteKey Lib “advapi32.dll” Alias “RegDeleteKeyA” (ByVal hKey As Long, ByVal lpSubKey As String) As Long

  参数:

   hKey:Key Handle

   lpSubKey:SubKey名称或者路径,若传入””[空字符串],表示删除Key本身。

   返回值: =0,表示成功;≠0,表示失败。

  示例





Dim hKey,ret As Long
ret = RegCreateKey(HKEY_LOCAL_MACHINE, “SOFTWARE\Hongqt\xiaoyuer”, hKey)
ret = RegOpenKey(HKEY_LOCAL_MACHINE, “SOFTWARE\Hongqt”, hKey)
ret = RegDeleteKey(hKey, “xiaoyuer”)’删除HKEY_LOCAL_MACHINE\SOFTWARE\Hongqt\xiaoyuer

  注意:

  如果我们利用RegDeleteKey函数删除一个含有SubKey的Key时,对于Windows98和Winnt来讲是不一样的。比如我们把上面的删除调用改成ret = RegDeleteKey(hKey, “”),则在windows98下,它会连hongqt下的xiaoyuer一起删除,而在winnt下则会报错。

  12.RegQueryInfoKey():返回注册表键的信息,包括类名、子键数量、最长子键名、值的数量、最长值数据、安全描述符的长度以及上一次写入的时间等。





RegQueryInfoKey(ByVal hKey As Long, ByVal lpClass As String, lpcbClass As Long, ByVal lpReserved As Long, lpcSubKeys As Long, lpcbMaxSubKeyLen As Long, lpcbMaxClassLen As Long, lpcValues As Long, lpcbMaxValueNameLen As Long, lpcbMaxValueLen As Long, lpcbSecurityDescriptor As Long, lpftLastWriteTime As FILETIME)

  参数:hKey–键句柄 lpClass–类型名称,仅使用于NT。若不使用则传入Null

   lpcbClass–传入lpClass参数长度,返回读取的长度 lpReserved–保留参数补0

   lpSubKeys–返回子键的数目 lpcbMaxSubKeyLen–返回最长的子键长度

   lpcbMaxClassLen–返回最长的类长度 lpcValues–返回值的数目

#p#副标题#e#

   lpcbMaxValueName–返回最长的值项名称的长度

   lpcbMaxValueLen–返回最长的值的长度

   lpcbSecurityDescriptor–返回安全描述,仅适用于 NT

   lpftLastWriteTime–返回键最后被写入的时间,仅适用于 NT

     返回值:=0 成功 ≠0 失败

  13.RegLoadKey():从指定的文件恢复注册表键的子键信息到注册表。





RegLoadKey(ByVal hKey As Long, ByVal lpSubKey As String, ByVal lpFile As String)
14.RegReplaceKey():从指定的文件恢复注册表键的子键信息到注册表并替换原有的值。

 



RegReplaceKey(ByVal hKey As Long, ByVal lpSubKey As String, ByVal lpNewFile As String, ByVal lpOldFile As String)

  15.RegRestoreKey():仅适用于Windows NT。从指定的文件中读取注册表键的信息并覆盖注册表中原有的值。





RegRestoreKey(ByVal hKey As Long, ByVal lpFile As String, ByVal dwFlags As Long)

  16. RegSaveKey():保存键及其子键信息到指定的文件。





RegSaveKey(ByVal hKey As Long, ByVal lpFile As String, lpSecurityAttributes As SECURITY_ATTRIBUTES)

  17. RegConnectRegistry():连接到远程系统的注册表。





RegConnectRegistry(ByVal lpMachineName As String, ByVal hKey As Long, phkResult As Long)

  18. RegNotifyChangeKeyValue():当修改指定的注册表对象时提供通知。





RegNotifyChangeKeyValue(ByVal hKey As Long, ByVal bWatchSubtree As Long, ByVal dwNotifyFilter As Long, ByVal hEvent As Long, ByVal fAsynchronus As Long)

  19. RegUnloadKey():删除注册表键及其所有的子键。





RegUnLoadKey(ByVal hKey As Long, ByVal lpSubKey As String)

  20. RegGetKeySecurity():检索指定键的安全信息。





RegGetKeySecurity(ByVal hKey As Long, ByVal SecurityInformation As Long, pSecurityDescriptor As SECURITY_DESCRIPTOR, lpcbSecurityDescriptor As Long)

  21. RegSetKeySecurity():设置指定键的安全信息。





RegSetKeySecurity(ByVal hKey As Long, ByVal SecurityInformation As Long, pSecurityDescriptor As SECURITY_DESCRIPTOR)

  最后给出两个函数是经过王国荣老师改编过的函数,与此相关,也一并列出。并且在我们的例子程序中要用到它们。RegEnumValueAsAny可以传入长整数和字符串;RegEnumValueAsAny2中lpData参数被改成Any后,可以使用Byte数组,由于Byte数组是采用”传地址方式来传递参数的,可以省下复制字符串数据的时间,使得程序变得更加高效。





Declare Function RegEnumValueAsAny Lib “advapi32.dll” Alias “RegEnumValueA” (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long

Declare Function RegEnumValueAsAny2 Lib “advapi32.dll” Alias “RegEnumValueA” (ByVal hKey As Long, ByVal dwIndex As Long, lpValueName As Any, lpcbValueName As Long, lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long

  参数说明:

   hKey:Key Handle

   dwIndex:欲读取之名称的顺序

   lpValueName:返回所读取的名称

   lpcbValueName:传入lpValueName参数的长度,返回所读取的名称的长度,注意这一长度不含chr(0)

   lpReserved:保留参数,实际使用时传入ByVal 0即可

   lpType:返回所读取的数据类型

   lpData:返回所读取的数据

   lpcbData:传入lpData,返回所读取的数据长度

   返回值: =0,表示成功;≠0,表示失败。

#p#副标题#e#

  调用例子:





ret=0
myindex=0
while ret=0
ret=RegEnumValue(hkey,myindex,Name,ByVal 0, typeData, ByVal vbNullString, lenData)
myindex=myindex+1
wend