一个提供注册表类型化访问的小类






3.78/5 (7投票s)
该类允许向 Windows 注册表写入/读取各种类型的值。
引言
当我从 Borland Delphi 迁移到 .NET 时,我发现标准 `RegistryKey` 类存在不足。Delphi 的 `TRegistry` 类中有 `WriteCurrency`、`WriteDate` 和 `WriteBinaryData` 等方法。在 .NET 2.0 中添加了一些处理 `RegistryValueKind` 枚举的有用方法。但仍然存在一个问题:例如,如何将 `System.Decimal` 类型的值保存在注册表项中。TypedRegistry 程序集包含一个类,该类允许向注册表项写入和读取以下类型的数据:`String`、`Byte[]`、`Int32`、`Boolean`、`DateTime`、`Decimal`、`Double`、`Guid`、`Int64`。
虽然 .NET 2.0 可以做到这一点,但值永远不会以 `REG_QWORD` 格式(在 Windows 2000 中引入)保存,因为 .NET 1.1 不支持这种格式。TypedRegistry 程序集旨在兼容两个 .NET 版本(1.1 和 2.0)。因此,`DateTime`、`Double` 和 `Int64` 类型的 8 字节值均保存为字节数组。
AcedRegistry 类
public class AcedRegistry : IDisposable
提供将类型化数据写入/读取到注册表的方法。
public AcedRegistry(AcedRootKey registryRootKey, string registryKey, bool writable)
打开由 `registryRootKey` 参数指定的根注册表项(例如 HKEY_CURRENT_USER 或 HKEY_LOCAL_MACHINE)。然后,打开 `registryKey` 参数传入的字符串表示的项。如果 `writable` 参数的值为 false
,则注册表项以只读模式打开。如果该值为 true
,则注册表项以读写模式打开(如果不存在则创建)。
例如,您可以在第一个参数中传递 `AcedRootKey.LocalMachine` 值,在 `registryKey` 参数中传递 @"Software\CompanyName\ApplicationName" 字符串。以下是 `registryRootKey` 参数的可能值列表。每个值对应于 `Microsoft.Win32.Registry` 类公开的根项的实例。
AcedRootKey.ClassesRoot
AcedRootKey.CurrentConfig
AcedRootKey.CurrentUser
AcedRootKey.DynData
AcedRootKey.LocalMachine
AcedRootKey.PerformanceData
AcedRootKey.Users
public Microsoft.Win32.RegistryKey RegistryKey { get; }
获取相关的 `Microsoft.Win32.RegistryKey` 类实例。如果在此类的构造函数中打开或创建注册表项时发生错误,此属性将返回 null
。
public void Dispose()
关闭相关的注册表项,如果其内容已被修改,则将其刷新到磁盘。
public void Put(string valueName, String value)
public void Put(string valueName, Byte[] value)
public void Put(string valueName, Int32 value)
public void Put(string valueName, Boolean value)
public void Put(string valueName, DateTime value)
public void Put(string valueName, Decimal value)
public void Put(string valueName, Double value)
public void Put(string valueName, Guid value)
public void Put(string valueName, Int64 value)
使用第一个参数(`valueName`)指定的名称,将 `value` 写入打开的注册表项。
public bool Get(string valueName, ref String value)
public bool Get(string valueName, ref Byte[] value)
public bool Get(string valueName, ref Int32 value)
public bool Get(string valueName, ref Boolean value)
public bool Get(string valueName, ref DateTime value)
public bool Get(string valueName, ref Decimal value)
public bool Get(string valueName, ref Double value)
public bool Get(string valueName, ref Guid value)
public bool Get(string valueName, ref Int64 value)
从打开的注册表项中读取具有指定名称(`valueName`)的相应类型的值。然后将其存储在 `value` 参数中。如果成功读取值,则方法返回 true
。如果当前注册表项中不存在具有该名称的值,则方法返回 false
,并且不修改 `value` 参数。
public String GetDef(string valueName, String defaultValue)
public Byte[] GetDef(string valueName, Byte[] defaultValue)
public Int32 GetDef(string valueName, Int32 defaultValue)
public Boolean GetDef(string valueName, Boolean defaultValue)
public DateTime GetDef(string valueName, DateTime defaultValue)
public Decimal GetDef(string valueName, Decimal defaultValue)
public Double GetDef(string valueName, Double defaultValue)
public Guid GetDef(string valueName, Guid defaultValue)
public Int64 GetDef(string valueName, Int64 defaultValue)
从打开的注册表项中读取具有指定名称(`valueName`)的相应类型的值,并将其作为方法的结果返回。如果相关的注册表项中不存在具有该名称的值,则方法返回 `defaultValue` 参数的值。
使用示例
以下代码片段演示了如何将程序配置保存和加载为注册表项中的一组值。
private const string
DemoRegistryKeyName = "Software\\TypedRegistryDemo",
cfgStringValueName = "StringValue",
cfgDateTimeValueName = "DateTimeValue",
cfgDecimalValueName = "DecimalValue",
cfgBooleanValueName = "BooleanValue",
cfgEnumValueName = "EnumerationElement",
cfgByteArrayValueName = "Image";
private static string _stringValue;
private static DateTime _dateTimeValue;
private static decimal _decimalValue;
private static bool _booleanValue;
private static MyColors _enumValue;
private static byte[] _byteArrayValue;
private static void SaveConfig()
{
using (AcedRegistry config =
new AcedRegistry(AcedRootKey.CurrentUser,
DemoRegistryKeyName, true))
{
config.Put(cfgStringValueName, _stringValue);
config.Put(cfgDateTimeValueName, _dateTimeValue);
config.Put(cfgDecimalValueName, _decimalValue);
config.Put(cfgBooleanValueName, _booleanValue);
config.Put(cfgEnumValueName, (int)_enumValue);
config.Put(cfgByteArrayValueName, _byteArrayValue);
}
}
private static void LoadConfig()
{
using (AcedRegistry config = new AcedRegistry(AcedRootKey.CurrentUser,
DemoRegistryKeyName, false))
{
config.Get(cfgStringValueName, ref _stringValue);
config.Get(cfgDateTimeValueName, ref _dateTimeValue);
config.Get(cfgDecimalValueName, ref _decimalValue);
config.Get(cfgBooleanValueName, ref _booleanValue);
_enumValue = (MyColors)config.GetDef(cfgEnumValueName, (int)_enumValue);
config.Get(cfgByteArrayValueName, ref _byteArrayValue);
}
}
将所有访问注册表的方法调用封装在 `using` 语句中是很方便的。这样,我们可以确保 `AcedRegistry` 类的实例将在末尾被释放,并且相关的标准 `RegistryKey` 类实例将被关闭。
我们甚至可以将自定义枚举类型的 `value` 作为 `System.Int32`(或可能是 `System.Int64`)类型的值保存在注册表中。在上面的代码片段中,我们在将 `MyColors` 枚举类型的值传递给 `Put` 方法之前,将其强制转换为 int
。然后,当从 `GetDef` 方法返回值时,我们将其强制转换回 `MyColors` 类型。
结论
所描述的类包含几种以类型化方式处理注册表数据的方法。这只是标准 `RegistryKey` 类的一个附加功能。要在此类工作时访问相关的 `RegistryKey`,请使用同名的属性。