使用VisualBasic读取和修改Windows注册表
在过去
,VisualBasic应用程序的开发者们对于如何在两次应用程序的运行之间保留状态信息感到非常的困难
。这是因为基于MicrosoftWindows的应用程序(包括VisualBasic)需要将应用程序的状态信息写入到一个文本文件(*.INI文件)中
,且需要经常对这些文件中的文本进行分析,以包含有用的状态信息
。 现在,随着Windows95以及WindowsNT这类32位操作系统的到来,应用程序可以通过使用一个叫做Windows注册表的存储场所来保留应用程序的状态信息,并且将它们自己注册在系统之中。通过位于ADVAPI32.DLL中的C语言应用程序
编程接口(APIs),对注册库的提取和修改变得非常容易。这对于使用C和C 的程序员来说真是太好了,不过对于那些使用其它
编程语言,例如VisualBasic的程序员来说,使用这些编程接口还需要进行许多额外的工作。
作为一个VB程序员,你首先必须在一个*.BAS文件中定义注册库函数的原形,这些函数原形必须同存储在ADVAPI32.DLL中的所需要的注册库APIs相兼容。你还需要添加那些对调用这些APIs所需要的结构和常量的声明。这些对函数原形,结构以及常量的声明全部包含在VBREG.BAS文件中,该文件是VBREG,本文的配套样例代码的一部份。要在任何32位的VB工程中使用这些注册库APIs,只需要简单地将VBREG.BAS文件包含在工程中。
注意:如果你决定在VBREG.BAS文件中添加额外的APIs,结构或常量,在对它们进行声明的时候需要格外小心(特别是这些函数的参数)。要想这些在你的VisualBasic代码中被调用的APIs按照你所预想的工作,正确声明这些函数的参数是异常重要的。许多这类声明的例子可以在WIN32API.TXT文件中找到,该文件作为VisualBasic系统的一部份同时被安装,但是你可能需要对这些声明进行修改,以便使它们能够正常工作。你还可以在WINNT.H文件中找到额外的一些有用的注册库常量,在WINERROR.H文件中找到额外的一些有用的错误常量,这些文件随着VisualC 一起被安装。
一旦你将一个文件,例如VBREG.BAS包括在你的工程中,你就可以在你的VB代码中调用这些注册库APIs。要记住的是你所转递的参数必须有效且包含有效的值。另外,当STRING值被返回时,必须为此字符串创建一个
空间来容纳它。这些APIs,结构以及常量在VBREG样例应用程序中都有说明。
Windows注册表通过四个主要注册关键字来组织:HKEY_CLASSES_ROOT,HKEY_CURRENT_USER,HEKY_LOCAL_MACHINE,以及HKEY_USERS。在本文中假设你对于这些关键字已经非常熟悉,已经知道如何使用子关键字,以及已经了解在注册库中所包含的值的类型。子关键字可以用“HighestSubkeyNextLevelSubkeyLowerLevelSubkey”(不包括引号)的形式来表示。其中“HighestSubkey”是最高级的子关键字,它直接位于四个主关键字之下。
注册关键字可以被创建,删除,打开,关闭。正如你可能所想到的,一个注册关键字在能够使用之前需要首先创建它,在对一个注册关键字进行修改之前必须要首先打开它。在应用程序执行期间,你应该关闭所有的当前未被使用的关键字,并且你应该仅仅只删除那些你能确定将来绝对不会再使用的关键字。
注册值可以被创建,查询,修改以及删除。一个值在它能够被查?之前必须已经被创建或是修改(通过使用RegSetValueEx来完成)。同注册关键字一样,如果你想删除它,你需要确定它将来绝对不会再被使用。
另外,注册关键字和值可以被枚举,以助你决定当前的那些输入是可以使用的。如果你在编译期间不能够确定对哪些关键字或值感兴趣,枚举功能就非常有用了。
有一点很有趣的注意事项是RegDeleteKeyAPI在没有子关键字的情况下将只删除注册关键字。由于这个原因,VBREG不允许删除一个带有子关键字的关键字。不过你能够很容易的添加删除关键字以及子关键字的功能,你只需要创建一个过程,该过程枚举你需要操作的关键字下的所有子关键字(以及这些子关键字的子关键字),并且在删除该关键字之前首先删除所有的子关键字。对于每个子关键字都应该在RegDeleteKey函数中检查ERROR_ACCESS_DENIED标志,这样的有效的递归进程能工作得很好。
VBREG使用HKEY_LOCAL_MACHINE,在如下的VBREGForm_Load()过程中被设置:hKey=HKEY_LOCAL_MACHINE
通过将此变量设置为其它的四个主注册关键字之一,你能够很容易的使用它们。更进一步,你能够从用户或是一个已知的注册库位置获取这些信息。
使用这些注册表APIs,一个比较好的方法是检查函数所返回的值以确定函数的调用是否成功(如果函数调用成功,它将会返回ERROR_SUCCESS标志)。如果不成功,你还可以检查错误值,基于错误发生的类型,你可以决定你的应用程序接下来该怎么做。还有一个比较好的方法是使用注册表APIs(例如在VBREG样例中的CreateRegKey函数)来为错误设置陷井,以决定你的应用程序在错误发生后的行为。
VBREG创建和修改的值都是REG_SZ类型(Unicode空结束字符串)的值。这里还有几种其它类型的值可以在注册库中使用,例如REG_BINARY,REG_LINK,以及REG_DWORD。例如,要写一个REG_DWORD类型来替换REG_SZ类型,则SetRegValue过程的RegSetValueEx调用应该被改为:
lResult=RegSetValueEx(phkResult,sSetValue,0,REG_DWORD,CInt(sValue),4&)
这里假设该“sValue”包含一个可以被转化为一个整数的值。你可能会需要在代码中进行更深入的修改以使用这些其它类型的值。
在你能够使用一个注册库关键字之前,该关键字必须被创建。RegCreateKeyExAPI提供了运行时刻的这个功能。如果关键字不存在,则RegCreateKeyEx将创建一个新的关键字,而如果关键字已经存在,则将只简单地将它打开。下面是在VBREG的CreateRegKey过程中对RegCreateKeyEx的调用。
CreateRegKey=(RegCreateKeyEx(hKey,SubKey&NewSubKey,0,"",_REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,_SA,phkResult,Create)=ERROR_SUCCESS)
如果RegCreateKeyEx函数返回了ERROR_SUCCESS标志,则你可以为REG_CREATED_NEW_KEY或REG_OPENED_EXISTING_KEY检查Create参数,以确定是否有一个新的关键字被创建。在上面的调用中,REG_OPTION_NON_VOLATILE创建一个持久的关键字,KEY_ALL_ACCESS则给予所有的用户对此关键字的完整的访问权利。其它的选项也同样能够被指定。这些选项在VisualC 所带的WindowsAPI参考中有更深入的解释。
一旦你有需要的注册表关键字,你可以使用RegOpenKey或RegKeyCreateEx来在将来需要的时候打开它们。你可能会注意到在VBREG中在看上去应该使用RegOpenKey的地方使用了RegKeyCreateEx。我发现如果不使用RegKeyCreateEx来打开此关键字,则有一些操作将会返回ERROR_ACCESS_DENIED标志。这可能会构成额外的开支;如果该关键字不存在的话它将会真正地创建此关键字。如果这不是你所需要的,你应该试着在调用RegCreateKeyEx之前首先调用RegOpenKey,然后看看它的调用是否成功。
一旦一个关键字被打开,你可以使用RegSetValueEx来设置它的值,如果需要的话,你也可以创建它。如果一个值还不存在,而你又不想创建它,你应该在调用RegSetValueEx之前首先调用RegQueryValueEx,然后测试它的返回值是不是ERROR_SUCCESS。下面是在VBREG的SetRegValue过程中对RegSetValueEx的调用:
lResult=RegSetValueEx(phkResult,sSetValue,0,REG_SZ,sValue,_CLng(Len(sValue) 1))
在上面的调用中,REG_SZ是被写入的值的类型。正如在前面所提到过的,如果你正确转递参数,你也可以写入其它类型的值。
你还可以通过使用RegQueryValueEx来在注册库中查询一个存在的值。如果此函数调用成功,它将会返回ERROR_SUCCESS标志。下面是VBREG的GetRetValue过程中的代码段:
'Creatthebuffer.
szBuffer=Space(255)
lBuffSize=Len(szBuffer)
'Openthekey.
RegOpenKeyEx(hKey,lpszSubKey,0,1,phkResult)
'Querythevalue
lResult=RegQueryValueEx(phkResult,szKey,0,0,szBuffer,lBuffSize)
在这里需要注意的最为重要的事情是要为缓冲创建足够的
空间。使用C语言APIs返回一个STRING值作为一个输出(out)参数(例如RegQueryValueEx的第5个参数),你必须显式地为此参数定义一个空间。如果这项操作失败,将会导致产生一个不可预料的结果值。
这篇文章意图告诉你在VisualBasic4.0应用程序中如何使用Windows注册表APIs。如果你希望看到更多的有关Windows注册表或注册表APIs的信息,请参考VisualC 所带的WindowsAPI参考,以及在Microsoft开发库(MicrosoftDevelopmentLibrary)中有关的文字。->