使用 C# 了解注册表的一切 (您想知道的),第 1 部分,共 2 部分






4.53/5 (71投票s)
2003年8月20日
9分钟阅读

364666
如何使用 C# 获取/设置/创建/删除系统、用户注册表项;设置注册表权限等。
涵盖的问题
本文是两部分文章的第一部分。本部分解释了如何
- 访问注册表项
- 创建新的子项
- 获取或设置现有值的数据
- 删除子项
- 获取子项列表
- 关闭子项
目录
引言
注册表是 Windows® 特有的存储库,用于存储有关应用程序、用户和默认系统设置的信息。当您的应用程序关闭时,如果您想在应用程序重新打开之前将数据存储在某个地方,注册表会派上用场。
由于注册表是 Windows® 特有的,它使用一个专属命名空间:Microsoft.Win32
。
一点理论
注册表有点像一个大型数据库。所有数据都以类似于键值对模型的格式存储,这意味着您将有一个键(类似于变量)及其关联的值。例如
Key: "ForeColor"
Value: "Red"
表示我们有一个键 ForeColor
,其值为 Red
。注册表中使用的格式的区别在于,它不使用键值对,而是使用值-数据对;因此,在这个例子中,ForeColor
是其数据为 Red
的值。
要了解注册表的结构,请查看您自己计算机的注册表。在“开始”->“运行”对话框中执行 _regedit.exe_ 来运行注册表编辑器。将打开一个类似于 Windows 资源管理器的新窗口。如果左侧的所有分支尚未折叠,请将其折叠。您将看到“我的电脑”下方分层排列的文件夹集合,每个文件夹都用于一个独特的目的和更好的组织。转到任何文件夹。在右侧,您将看到一些值及其各自数据的详细视图。
Windows® 在注册表中存储了大量数据。此外,用户计算机中安装的大多数应用程序也会将自己的设置存储在注册表中。作为如此庞大数据的存储库,注册表需要组织良好。正是因为这个原因,注册表被划分成您刚才看到的清晰的分层文件夹集合。
现在是时候准备一些代码了。
代码解释
命名约定
在处理注册表时,您可能会遇到的一个问题是用于表示注册表各种元素的不同名称混淆。因此,在我们继续编写代码之前,我们将理清这一点。注册表中主要有四个元素:根键、子键、值和数据。请参阅下面给出的注册表编辑器截图以了解它们。
正如您可能从图片中猜到的那样,每当您在 .NET 中使用注册表时,都需要两个类:Microsoft.Win32.RegistryKey
和 Microsoft.Win32.Registry
。RegistryKey
类用于表示注册表中的任何子键。而 Registry
类仅用于表示注册表中的根键。根键只不过是特殊类型的子键——它们构成注册表中的顶级键。最终,无论您选择哪个键,它都将是 RegistryKey
类型。再次查看图像并确保一切清晰。如果完成,让我们继续编写一些代码。
选择一个子项
无论您想对注册表做什么,都必须首先选择一个子项。要选择一个子项,您需要首先访问该子项的根项。选择根项后,您需要创建一个新的 RegistryKey
对象来获取对您的子项的访问。
所以,首先,我们将选择一个根键。所有根键都作为字段列在 Microsoft.Win32.Registry
中。要选择一个根键,您可以使用 Microsoft.Win32.Registry
类中相应的字段。重要的字段是
字段名 | 用途 | 描述 |
ClassesRoot |
访问 HKEY_CLASSES_ROOT |
文件类型、组件等信息。 |
CurrentConfig |
访问 HKEY_CURRENT_CONFIG |
当前硬件信息 |
CurrentUser |
访问 HKEY_CURRENT_USER |
当前用户信息 |
LocalMachine |
访问 HKEY_LOCAL_MACHINE |
当前机器的配置信息 |
用户 |
访问 HKEY_USERS |
默认用户配置信息 |
请注意,由于根键构成了注册表的生命和灵魂,这些字段都是只读的。它们用于在其下创建子键,而不是修改它们。
选择根键字段后,我们需要创建一个新的 RegistryKey
对象。为此,您可以在选择的相应根键字段上调用静态 RegistryKey.OpenSubKey
或 RegistryKey.CreateSubKey
方法。首先让我们看看如何使用 RegistryKey.CreateSubKey
方法创建一个新的子键。
创建新子键
要创建新子键,请使用 RegistryKey.CreateSubKey
方法,其定义为
public RegistryKey CreateSubKey(string subkey);
其中字符串 subkey
表示要创建的子键的名称或路径。通常,其形式为:key name\Company Name\Application Name\version
。例如,任何 Windows® 条目都位于:SOFTWARE\Microsoft\Windows
。您可以打开注册表亲自查看。
如果出现错误,此方法将返回子项或返回 null
并引发异常。失败的可能原因包括权限不足、不存在此类键等。所有异常将在本文的第 2 部分中处理。
使用示例:
...
RegistryKey MyReg = Registry.CurrentUser.CreateSubKey
("SOFTWARE\\SomeCompany\\SomeApp\\SomeVer");
...
这将在 CurrentUser
根键下使用指定的路径创建一个新子键,并返回表示该子键的 RegistryKey
对象。
几点说明
- 如果已经存在一个与您在参数
subkey
中传递的名称相同的子键,则返回该子键;不会创建新的子键。因此,您实际上可以使用CreateSubKey
方法来创建或打开子键。 CreateSubKey
方法始终以写入模式返回子项(当然!)。- 如果您再次调用
CreateSubKey
(在已经创建了一个子键之后),将在当前子键下创建新的子子键。
打开现有子键
要打开现有子键,请使用 RegistryKey.OpenSubKey
方法。您这样调用它
RegistryKey MyReg = Registry.CurrentUser.OpenSubKey(...);
OpenSubKey
有两个重载
public RegistryKey OpenSubKey(string name);
返回只读模式的子项,以及
public RegistryKey OpenSubKey(string name, bool writable);
根据布尔值 writable
指定的模式返回子键——如果 writable
为 true
,则为写入模式;如果为 false
,则为读取模式。在这两种方法中,字符串 name
表示您要打开的子键的路径。
因此,设置路径并将其传递给方法。如果一切顺利,您将返回 RegistryKey
对象。否则,将返回 null
。失败的可能原因与前面提到的相同。
例如
...
RegistryKey MyReg = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\SomeCompany\\SomeApp\\SomeVer", true);
...
如果子项存在,则从 CurrentUser
根键返回具有指定路径的 RegistryKey
对象,并处于写入模式。
获取值的数据
一旦(并且仅当)您拥有有效的 RegistryKey
对象,就可以访问子键的值及其数据。首先,让我们看看如何检索数据。要获取与子键中的值关联的数据,您可以使用 RegistryKey.GetValue
方法。它的调用方式如下
someRegistryKeyobject.GetValue(...);
GetValue
方法有两个重载
public object GetValue(string name);
返回与子键中由 name
表示的值关联的数据,如果该值不存在则返回 null
,以及
public object GetValue(string name, object defaultValue);
返回与子键中由 name
表示的值关联的数据,或由对象 defaultValue
指定的默认值。
显而易见,GetValue
返回 object
类型的数据。因此,您需要将其类型转换为所需的适当类型。
设置值的数据
现在,我们将看看如何设置值的数据。为此,我们使用定义如下的 RegistryKey.SetValue
方法
public void SetValue(string name, object value);
字符串 name
表示存储数据的值的名称。对象 value
表示您要存储的数据。由于 value
的类型是 object
,您可以向它传递任何对象。它在内部会被转换为 DWORD
、二进制或 string
。这就是为什么 RegistryKey.GetValue
方法返回 object
类型而不是原始类型的数据的原因。
要在子键的默认值中存储数据,只需将 name
设置为空字符串即可。
关闭子项
访问完子键后,需要将其关闭。只有当您关闭子键时,所做的修改才会写入注册表(这个过程称为“刷新”)。您使用 RegistryKey.Close
方法来关闭子键。
一个示例代码
...
RegistryKey MyReg = Registry.CurrentUser.CreateSubKey
("SOFTWARE\\SomeCompany\\SomeApp\\SomeVer");
int nSomeVal = (int)MyReg.GetValue("SomeVal", 0);
MyReg.SetValue("SomeValue", nSomeVal+1);
MyReg.Close();
...
看,很简单吧!
杂项
到目前为止所处理的都是一些非常基本的东西。现在让我们转向一些即使您可能不使用,但在某些情况下也很有用的东西。
删除子项
要删除子项,请使用 RegistryKey.DeleteSubKey
方法的两个重载之一
public void DeleteSubKey(string subkey);
删除 subkey
中指定的子项(前提是子项存在且其中没有子键或子子项),以及
public void DeleteSubKey(string subkey, bool throwOnMissingSubKey);
删除 subkey
中指定的子键(条件同上),如果找不到子键,则在 throwOnMissingSubKey
为 true
时引发异常。
删除整个树
要删除包括子键、值等在内的整个子键树,您可以使用 RegistryKey.DeleteSubKeyTree
方法
public void DeleteSubKeyTree(string subkey);
现在您应该知道这些参数的含义了。
删除一个值
要删除值,请使用 RegistryKey.DeleteValue
方法的 2 个重载之一
public void DeleteValue(string name);
其中,如果存在名称由 name
指定的值,则将其删除;否则抛出异常,并且
public void DeleteValue(string name, bool throwOnMissingValue);
与上一个重载相同,只是仅当布尔参数 throwOnMissingValue
为 true
时才抛出异常。
获取子项列表
要获取当前 RegistryKey
对象中存在的所有子项(子键)的列表,请使用 RegistryKey.GetSubKeyNames
方法
public string[] GetSubKeyNames();
它返回一个字符串数组。
获取值名称列表
要获取当前 RegistryKey
对象中存在的所有值的列表,请使用 RegistryKey.GetValueNames
方法
public string[] GetValueNames();
它返回一个字符串数组。
手动刷新
如果您想手动刷新,请调用 RegistryKey.Flush
方法。当您调用 RegistryKey.Close
方法时,对象会自动刷新,因此除非在最必要的情况下,您不需要手动刷新。
public void Flush();
第 1 部分结束
本文重点向您介绍了如何对注册表进行基本操作。在下一篇文章——第 2 部分中,主要关注点将是注册表的安全性、权限以及访问注册表时不同方法抛出的异常等。
附注:正如 Microsoft® 始终警告的那样,在您使用注册表之前请备份它 :-)