在.NET Compact Framework中,Microsoft.Win32命名空间只提供处理操作系统注册表的类和对象。表18-3列出了Microsoft.Win32命名空间支持的类和对象。
表18-3 Microsoft.Win32命名空间支持的类和对象
类名
|
说明
|
Registry
|
提供表示
Windows
注册表中的根项的
RegistryKey
对象,并提供访问项
/
值对的
static
方法
|
RegistryKey
|
表示
Windows
注册表中的项级节点。此类是注册表封装
|
RegistryKeyPermissionCheck
|
指定在打开注册表项并访问它们的名称
/
值对时是否执行安全检查
|
RegistryValueKind
|
指定在注册表中存储值时所用的数据类型,或标识注册表中某个值的数据类型
|
Registry类包含在Windows Mobile的注册表中能找到的标准子树集。由Registry类公开的RegistryKey实例,描绘注册表中的子树项和值的基本存储机制。所有的项都是只读的,因为注册表依赖于它们的存在。由Registry类以静态成员的方式公开的子树有:
· CurrentUser 存储有关用户首选项的信息。
· LocalMachine 存储本地计算机的配置信息。
· ClassesRoot 存储有关类型(和类)及其属性的信息。
· Users 存储有关默认用户配置的信息。
一旦标识了希望在其下存储/检索注册表信息的子树后,就可以开始使用RegistryKey类创建或删除子项和给指定项赋值。
18.3.1 创建注册表子项
在.NET Compact Framework中,可以调用RegistryKey类的CreateSubKey方法来实现创建注册表子项的功能。调用CreateSubKey方法,创建一个新子项或打开一个现有子项以进行写访问。.NET Compact Framework只提供了CreateSubKey方法的一种重载版本。该方法的声明语法如下:
Public Function CreateSubKey (ByVal subkey As String) As RegistryKey
字符串subkey不区分大小写,指定要创建或打开的子项的名称或路径。CreateSubKey方法返回一个标识新建子项的RegistryKey对象。如果操作失败,则返回空引用(在Visual Basic中为Nothing)。如果为subkey指定了零长度字符串,则返回当前的RegistryKey对象。以下代码演示调用RegistryKey类的CreateSubKey方法。
……
' 在 HKEY_CURRENT_USER 下创建一个名为 RegistryDemo 的子项
Dim RegistryDemo As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.CurrentUser.CreateSubKey("RegistryDemo")
' 在 HKEY_CURRENT_USER/RegistryDemo 下创建两个子项
RegistryDemo.CreateSubKey("TestName").Close()
Dim TestSettings As Microsoft.Win32.RegistryKey = RegistryDemo.CreateSubKey("TestSettings")
' 关闭 RegistryKey 实例
TestSettings.Close()
RegistryDemo.Close()
……
18.3.2 读取注册表子项
读取注册表子项的功能指检索根项或指定子项的子项。RegistryKey类的GetSubKey Names方法能够非常方便地检索根项或指定子项的子项。GetSubKeyNames方法的声明语法如下:
Public Function GetSubKeyNames As String()
GetSubKeyNames方法返回一个包含当前项的子项名称的字符串数组。以下代码演示调用RegistryKey类的GetSubKeyNames方法,检索HKEY_CURRENT_USER的所有子项。
……
Dim subKeyName As String
Dim subkeys As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser
' 返回 HKEY_CURRENT_USER 的所有子项
Dim keynames As String() = subkeys.GetSubKeyNames()
' 显示子项名称
For Each subKeyName In keynames
MsgBox(subKeyName)
Next
subkeys.Close()
……
18.3.3 创建注册表值项
创建注册表值项的功能是指设置注册表项中的名称/值对的值。通过RegistryKey类的SetValue方法和Registry类的SetValue方法,都可以实现创建注册表值项的功能。但是每次使用Registry类的SetValue方法时,SetValue方法都会尝试打开和关闭注册表项,所以当访问大数据量的值项时,建议使用RegistryKey类的SetValue方法来保证更好的性能。在.NET Compact Framework中,RegistryKey类的SetValue方法提供两个重载版本,其声明语法如下:
Public Shared Sub SetValue ( _
ByVal keyName As String, _
ByVal valueName As String, _
ByVal value As Object, _
)
Public Shared Sub SetValue ( _
ByVal keyName As String, _
ByVal valueName As String, _
ByVal value As Object, _
ByVal valueKind As RegistryValueKind _
)
SetValue方法的通过RegistryValueKind参数指定的注册表枚举数据类型,设置该指定的注册表项的名称/值对。如果指定的值项不存在,则创建该值项。注册表值项,可具有与任何名称都不关联的值。如果注册表编辑器中显示此未命名的值,则会出现字符串“(Default)”,而不会出现值项的名称。若要设置这个未命名的值,则指定valueName为空引用或空字符串即可。如果指定的value类型与指定的valueKind不匹配,并且无法转换数据,则会抛出ArgumentException例外。
以下代码演示调用RegistryKey类的SetValue方法设置TestSettings子项的3个名称/值对:
……
' 在 HKEY_CURRENT_USER 下创建一个名为 RegistryDemo 的子项
Dim RegistryDemo As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.CurrentUser.CreateSubKey("RegistryDemo")
' 在 HKEY_CURRENT_USER/RegistryDemo 下创建两个子项
RegistryDemo.CreateSubKey("TestName").Close()
Dim TestSettings As Microsoft.Win32.RegistryKey = RegistryDemo.CreateSubKey("TestSettings")
' 设置 TestSettings 子项的3个名称/值对
Dim myStrings() As String = {"One", "Two", "Three"}
TestSettings.SetValue("TestArray", myStrings)
TestSettings.SetValue("语言", "英语")
TestSettings.SetValue("级别", "CET-6")
TestSettings.SetValue("ID", 1001)
' 关闭 RegistryKey 实例
TestSettings.Close()
RegistryDemo.Close()
……
18.3.4 读取注册表值项
读取注册表值项的功能,包括检索与指定子项关联的所有值名称和值项所对应的值两部分功能。通过RegistryKey类的GetValueNames方法,可以实现检索与指定子项关联的所有值名称的功能。通过RegistryKey类的GetValue方法和Registry类的GetValue方法,都可以实现检索子项所对应项值的功能。但是每次使用Registry类的GetValue方法时,GetValue方法都会尝试打开和关闭注册表项,所以当访问大数据量的值项时,建议使用RegistryKey类的GetValue方法。RegistryKey类的GetValueNames方法的声明语法如下:
Public Function GetValueNames As String()
在.NET Compact Framework中,RegistryKey类的GetValue方法提供两个重载版本,其声明语法如下:
Public Function GetValue (ByVal name As String) As Object
Public Function GetValue (ByVal name As String, ByVal defaultValue As Object) As Object
GetValueNames方法返回一个包含与此项关联的所有值名称的字符串数组。如果未找到此项的值名称,则返回一个空数组。注册表子项可以有一个默认值,该默认值的名称为空字符串("")的名称/值对。如果为注册表子项设置了默认值,则GetValueNames方法返回的数组包含该空字符串。
GetValue方法返回一个与指定注册表项中的指定名称关联的值。如果在指定的项中未找到该名称,则返回用户提供的默认值;或者如果指定的项不存在,则返回空引用。以下代码演示调用RegistryKey类的GetValueNames方法,检索TestSettings子项的所有值项的名称,并通过GetValue方法显示值项对应的值。
……
Dim valueName As String
Dim subkeys As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.CurrentUser.OpenSubKey("RegistryDemo/TestSettings")
' 返回 TestSettings 的所有值项
Dim keyvalues As String() = subkeys.GetValueNames()
' 显示值项名称和对应的值
For Each valueName In keyvalues
MsgBox("名称/值对 " & valueName & "=" & subkeys.GetValue(valueName).ToString())
Next
subkeys.Close()
……
18.3.5 删除注册表子项
在.NET Compact Framework中,提供了两种删除注册表子项的方法。分别是RegistryKey类的DeleteSubKeyTree和DeleteSubKey方法。DeleteSubKeyTree方法递归删除指定子项以及该子项所包括的任何子项。DeleteSubKey方法删除指定的子项。在.NET Compact Framework中,DeleteSubKey方法提供两个重载版本。DeleteSubKeyTree和DeleteSubKey方法的声明语法如下:
Public Sub DeleteSubKeyTree (ByVal subkey As String)
Public Sub DeleteSubKey (ByVal subkey As String)
Public Sub DeleteSubKey (ByVal subkey As String, ByVal throwOnMissingSubKey As Boolean)
RegistryKey类的这两个方法的字符串参数subkey均不区分大小写。使用DeleteSubKeyTree方法删除指定子项时,将删除目录树中该项下的所有项,并且不提供任何警告提示。如果仅希望删除不包括其他子项的子项时,可以使用DeleteSubKey方法。DeleteSubKey方法的throwOnMissingSubKey参数,指示在找不到指定子项的情况下是否引发异常。如果该参数为true,并且指定的子项不存在,则引发异常;如果该参数为false,并且指定的子项不存在,则不执行任何操作。以下代码演示调用RegistryKey类的DeleteSubKey和DeleteSubKeyTree方法,分别删除子项TestSettings和RegistryDemo。
……
' 删除子项 TestSettings 和 RegistryDemo
Microsoft.Win32.Registry.CurrentUser.DeleteSubKey("RegistryDemo/TestName")
Microsoft.Win32.Registry.CurrentUser.DeleteSubKeyTree("RegistryDemo")
……
18.3.6 删除注册表值项
删除注册表值项的功能是指从当前子项中删除指定的值项。通过RegistryKey类的DeleteValue方法,可以实现删除注册表值项的功能。在.NET Compact Framework中,RegistryKey类的DeleteValue方法提供两个重载版本,其声明语法如下:
Public Sub DeleteValue (ByVal name As String)
Public Sub DeleteValue (ByVal name As String, ByVal throwOnMissingValue As Boolean)
DeleteValue方法通过RegistryValueKind参数指定的注册表枚举数据类型,设置该指定的注册表项的名称/值对。DeleteValue方法的throwOnMissingSubKey参数,指示在找不到指定值的情况下是否引发异常。如果该参数为True,并且指定的值项不存在,则引发异常;如果该参数为False,并且指定的值项不存在,则不执行任何操作。以下代码演示调用RegistryKey类的DeleteValue方法删除值项TestArray。
……
Dim testSettings As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.CurrentUser.OpenSubKey("RegistryDemo/TestSettings")
' 删除值项 TestArray
testSettings.DeleteValue("TestArray")
testSettings.Close()
……
18.3.7 注册表数据类型
表18-2列出了.NET Compact Framework 2.0支持的7种常用的Windows Mobile注册表数据类型。这7种注册表数据类型的定义,包含在Microsoft.Win32命名空间的枚举对象RegistryValueKind里。
设置注册表项的值时,应该使用SetValue方法显式地指定注册表数据类型。检索和显示注册表项的值时,应该先使用GetValueKind方法检查注册表数据类型。
表18-2 Windows Mobile注册表数据类型
数据类型
|
说明
|
String
|
固定长度的文本字符串。此值与
Win32 API
注册表数据类型
REG_SZ
等效
|
Binary
|
指定任意格式的二进制数据。此值与
Win32 API
注册表数据类型
REG_BINARY
等效
|
DWORD
|
数据由
4
字节长的数表示。设备驱动程序和服务的很多参数都是这种类型,这些参数在注册表编辑器中是以二进制、十六进制或十进制的格式显示的。此值与
Win32 API
注册表数据类型
REG_DWORD
等效
|
MultiString
|
多重字符串。包含列表或多值(其格式可被用户读取)的值通常为该类型。各个值项之间可以使用空格、逗号或其他标记分开。此值与
Win32 API
注册表数据类型
REG_MULTI_SZ
等效
|
ExpandString
|
指定一个以
NULL
结尾的字符串,该字符串中包含对环境变量(如
%PATH%
,当值被检索时,就会展开)的未展开的引用。此值与
Win32 API
注册表数据类型
REG_EXPAND_SZ
等效
|
QWord
|
指定一个
64
位二进制数。此值与
Win32 API
注册表数据类型
REG_QWORD
等效
|
Unknown
|
指示一个不受支持的注册表数据类型。例如,不支持
Microsoft Win32 API
注册表数据类型
REG_RESOURCE_LIST
。使用此值指定
SetValue
方法,应在存储名称
/
值对时确定适当的注册表数据类型
|
清单18-1演示调用RegistryKey类的SetValue、GetValueKind方法和枚举对象RegistryValueKind设置及检查显示各种类型的注册表数据。
清单18-1 设置及检查显示各种类型的注册表数据
……
Dim rk As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.CurrentUser.CreateSubKey("RegistryDemo/RegistryValueKindExample")
' 创建名称/值对
rk.SetValue("QuadWordValue", 42, Microsoft.Win32.RegistryValueKind.QWord)
rk.SetValue("DWordValue", 42, Microsoft.Win32.RegistryValueKind.DWord)
rk.SetValue("MultipleStringValue", New String() {"One", "Two", "Three"}, _
Microsoft.Win32.RegistryValueKind.MultiString)
rk.SetValue("BinaryValue", New Byte() {10, 43, 44, 45, 14, 255}, _
Microsoft.Win32.RegistryValueKind.Binary)
rk.SetValue("StringValue", "The path is %PATH%", Microsoft.Win32.RegistryValueKind.String)
rk.SetValue("ExpandedStringValue", "The path is %PATH%", _
Microsoft.Win32.RegistryValueKind.ExpandString)
' 显示名称/值对
Dim valueNames As String() = rk.GetValueNames()
Dim s As String
For Each s In valueNames
Dim rvk As Microsoft.Win32.RegistryValueKind = rk.GetValueKind(s)
Select Case rvk
Case Microsoft.Win32.RegistryValueKind.MultiString
Dim values As String() = CType(rk.GetValue(s), String())
MsgBox(s & ":" & rvk & ":" & values(0))
Dim i As Integer
For i = 1 To values.Length - 1
MsgBox(i & ":" & values(i))
Next
Case Microsoft.Win32.RegistryValueKind.Binary
Dim bytes As Byte() = CType(rk.GetValue(s), Byte())
MsgBox(s & ":" & rvk & ":" & bytes(0))
Dim i As Integer
For i = 1 To bytes.Length - 1
MsgBox(s & ":" & bytes(i))
Next
Case Else
MsgBox(s & ":" & rvk & ":" & rk.GetValue(s))
End Select
Next
……
执行清单18-1的代码,向Pocket PC设备注册表写入数据的结果如图18-3所示。
图18-3 各种类型的注册表数据
通过本章的介绍,应该对如何使用Windows Mobile注册表有了一定的了解。接下来通过介绍一个Pocket PC设备的注册表应用实例来加深感性认识。
每个Pocket PC设备都提供有记录设备用户信息的功能。可以在Pocket PC应用程序的Logo界面里显示设备用户的姓名、工作单位和电子邮件等信息。在Windows Mobile for Pocket PC里,设备用户信息存储在注册表中,因此可以通过Pocket PC应用程序来读取设备用户信息。
清单18-2演示从注册表里读取设备用户的姓名、单位、地址、电话和电子邮件信息。
清单18-2 读取设备用户信息
……
Dim RegData() As Byte = Nothing
Dim RegRead As Microsoft.Win32.RegistryKey
Try
RegRead = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("/ControlPanel/Owner", True)
If Not (RegRead Is Nothing) Then
RegData = RegRead.GetValue("Owner")
End If
RegRead.Close()
lb_owner_info.Items.Clear()
lb_owner_info.Items.Add( _
"姓名:" + System.Text.Encoding.Unicode.GetString(RegData, 0, 72).TrimEnd + vbCrLf)
lb_owner_info.Items.Add( _
"单位:" + System.Text.Encoding.Unicode.GetString(RegData, 72, 72).TrimEnd + vbCrLf)
lb_owner_info.Items.Add( _
"地址:" + System.Text.Encoding.Unicode.GetString(RegData, 144, 372).TrimEnd + vbCrLf)
lb_owner_info.Items.Add( _
"电话:" + System.Text.Encoding.Unicode.GetString(RegData, 516, 50).TrimEnd + vbCrLf)
lb_owner_info.Items.Add( _
"电子邮件:" + System.Text.Encoding.Unicode.GetString(RegData, 566, 74).TrimEnd + vbCrLf)
Catch ex As System.Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "警告")
End Try
……
执行清单18-2的代码,从Pocket PC设备注册表读取设备用户信息的结果如图18-4所示。