C# 从 RegistryKey 获取 BaseKey
C# Get BaseKey from RegistryKey
我有一个打开的注册表子项,例如 HKEY_CURRENT_USER\SOFTWARE\Microsoft。如何摆脱 Base Registry Key 或 Registry Hive?
RegistryKey.OpenBaseKey(RegistryHive, RegistryView) 方法没有向其传递 RegistryKey 或字符串的重载。
我写了下面的代码:
// OUR INPUT:
RegistryKey inputKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft");
string subKeyName = subkey.ToString();
string hiveName = subKeyName.Substring(0, subKeyName.IndexOf('\'));
RegistryHive regHive;
switch (hiveName)
{
case "HKEY_CLASSES_ROOT": regHive = RegistryHive.ClassesRoot; break;
case "HKEY_CURRENT_USER": regHive = RegistryHive.CurrentUser; break;
case "HKEY_LOCAL_MACHINE": regHive = RegistryHive.LocalMachine; break;
case "HKEY_USERS": regHive = RegistryHive.Users; break;
case "PerformanceData": regHive = RegistryHive.LocalMachine; break;
case "CurrentConfig": regHive = RegistryHive.CurrentConfig; break;
case "DynData": regHive = RegistryHive.DynData; break;
default: throw new System.ArgumentOutOfRangeException();
}
// OUR TARGET:
RegistryKey baseKey = RegistryKey.OpenBaseKey(regHive, RegistryView.Default);
它有效,但在我看来应该有更好的解决方案。
也许你知道另一个解决方案?
你基本上走在了正确的轨道上,正在做能做的一切。
registry class 只是 win32 API 的包装,没有真正的魔法在这里继续并在 string 路径上工作 registry 和 hives。
更多链接:
您可以在此处查看文档,RegistryKey Class
在这里深入研究源代码,registrykey.cs
这里是madreflection添加的Win32注册表api,winreg.h header
正如您已经注意到的,没有更简单的方法可以实现您的预期目标
@TheGeneral,感谢 link 源代码。在registry.cs中,我找到了一个可以满足我需要的方法。不幸的是,它是私有方法,我们需要在我们的项目中重新编写它:
微软解决方案:
// Following function will parse a keyName and returns the basekey for it.
// It will also store the subkey name in the out parameter.
// If the keyName is not valid, we will throw ArgumentException.
// The return value shouldn't be null.
//
[System.Security.SecurityCritical] // auto-generated
private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subKeyName) {
if( keyName == null) {
throw new ArgumentNullException("keyName");
}
string basekeyName;
int i = keyName.IndexOf('\');
if( i != -1) {
basekeyName = keyName.Substring(0, i).ToUpper(System.Globalization.CultureInfo.InvariantCulture);
}
else {
basekeyName = keyName.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
}
RegistryKey basekey = null;
switch(basekeyName) {
case "HKEY_CURRENT_USER":
basekey = Registry.CurrentUser;
break;
case "HKEY_LOCAL_MACHINE":
basekey = Registry.LocalMachine;
break;
case "HKEY_CLASSES_ROOT":
basekey = Registry.ClassesRoot;
break;
case "HKEY_USERS":
basekey = Registry.Users;
break;
case "HKEY_PERFORMANCE_DATA":
basekey = Registry.PerformanceData;
break;
case "HKEY_CURRENT_CONFIG":
basekey = Registry.CurrentConfig;
break;
case "HKEY_DYN_DATA":
basekey = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA);
break;
default:
throw new ArgumentException(Environment.GetResourceString("Arg_RegInvalidKeyName", "keyName"));
}
if( i == -1 || i == keyName.Length) {
subKeyName = string.Empty;
}
else {
subKeyName = keyName.Substring(i + 1, keyName.Length - i - 1);
}
return basekey;
}
我的解决方案:我将其重写为扩展方法:
public static RegistryHive GetRegistryHive(this RegistryKey key)
{
if (key == null)
{
throw new System.ArgumentNullException(nameof(key));
}
int i = key.Name.IndexOf('\');
string basekeyName = (i != -1) ? key.Name.Substring(0, i) : key.Name;
switch (basekeyName)
{
case "HKEY_CLASSES_ROOT": return RegistryHive.ClassesRoot;
case "HKEY_CURRENT_USER": return RegistryHive.CurrentUser;
case "HKEY_LOCAL_MACHINE": return RegistryHive.LocalMachine;
case "HKEY_USERS": return RegistryHive.Users;
case "HKEY_PERFORMANCE_DATA": return RegistryHive.LocalMachine;
case "HKEY_CURRENT_CONFIG": return RegistryHive.CurrentConfig;
case "HKEY_DYN_DATA": return RegistryHive.DynData;
default: throw new System.ArgumentException(nameof(basekeyName));
}
}
public static RegistryKey OpenBaseKey(this RegistryKey key)
{
return RegistryKey.OpenBaseKey(GetRegistryHive(key), key.View);
}
我有一个打开的注册表子项,例如 HKEY_CURRENT_USER\SOFTWARE\Microsoft。如何摆脱 Base Registry Key 或 Registry Hive?
RegistryKey.OpenBaseKey(RegistryHive, RegistryView) 方法没有向其传递 RegistryKey 或字符串的重载。
我写了下面的代码:
// OUR INPUT:
RegistryKey inputKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\Microsoft");
string subKeyName = subkey.ToString();
string hiveName = subKeyName.Substring(0, subKeyName.IndexOf('\'));
RegistryHive regHive;
switch (hiveName)
{
case "HKEY_CLASSES_ROOT": regHive = RegistryHive.ClassesRoot; break;
case "HKEY_CURRENT_USER": regHive = RegistryHive.CurrentUser; break;
case "HKEY_LOCAL_MACHINE": regHive = RegistryHive.LocalMachine; break;
case "HKEY_USERS": regHive = RegistryHive.Users; break;
case "PerformanceData": regHive = RegistryHive.LocalMachine; break;
case "CurrentConfig": regHive = RegistryHive.CurrentConfig; break;
case "DynData": regHive = RegistryHive.DynData; break;
default: throw new System.ArgumentOutOfRangeException();
}
// OUR TARGET:
RegistryKey baseKey = RegistryKey.OpenBaseKey(regHive, RegistryView.Default);
它有效,但在我看来应该有更好的解决方案。
也许你知道另一个解决方案?
你基本上走在了正确的轨道上,正在做能做的一切。
registry class 只是 win32 API 的包装,没有真正的魔法在这里继续并在 string 路径上工作 registry 和 hives。
更多链接:
您可以在此处查看文档,RegistryKey Class
在这里深入研究源代码,registrykey.cs
这里是madreflection添加的Win32注册表api,winreg.h header
正如您已经注意到的,没有更简单的方法可以实现您的预期目标
@TheGeneral,感谢 link 源代码。在registry.cs中,我找到了一个可以满足我需要的方法。不幸的是,它是私有方法,我们需要在我们的项目中重新编写它:
微软解决方案:
// Following function will parse a keyName and returns the basekey for it.
// It will also store the subkey name in the out parameter.
// If the keyName is not valid, we will throw ArgumentException.
// The return value shouldn't be null.
//
[System.Security.SecurityCritical] // auto-generated
private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subKeyName) {
if( keyName == null) {
throw new ArgumentNullException("keyName");
}
string basekeyName;
int i = keyName.IndexOf('\');
if( i != -1) {
basekeyName = keyName.Substring(0, i).ToUpper(System.Globalization.CultureInfo.InvariantCulture);
}
else {
basekeyName = keyName.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
}
RegistryKey basekey = null;
switch(basekeyName) {
case "HKEY_CURRENT_USER":
basekey = Registry.CurrentUser;
break;
case "HKEY_LOCAL_MACHINE":
basekey = Registry.LocalMachine;
break;
case "HKEY_CLASSES_ROOT":
basekey = Registry.ClassesRoot;
break;
case "HKEY_USERS":
basekey = Registry.Users;
break;
case "HKEY_PERFORMANCE_DATA":
basekey = Registry.PerformanceData;
break;
case "HKEY_CURRENT_CONFIG":
basekey = Registry.CurrentConfig;
break;
case "HKEY_DYN_DATA":
basekey = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA);
break;
default:
throw new ArgumentException(Environment.GetResourceString("Arg_RegInvalidKeyName", "keyName"));
}
if( i == -1 || i == keyName.Length) {
subKeyName = string.Empty;
}
else {
subKeyName = keyName.Substring(i + 1, keyName.Length - i - 1);
}
return basekey;
}
我的解决方案:我将其重写为扩展方法:
public static RegistryHive GetRegistryHive(this RegistryKey key)
{
if (key == null)
{
throw new System.ArgumentNullException(nameof(key));
}
int i = key.Name.IndexOf('\');
string basekeyName = (i != -1) ? key.Name.Substring(0, i) : key.Name;
switch (basekeyName)
{
case "HKEY_CLASSES_ROOT": return RegistryHive.ClassesRoot;
case "HKEY_CURRENT_USER": return RegistryHive.CurrentUser;
case "HKEY_LOCAL_MACHINE": return RegistryHive.LocalMachine;
case "HKEY_USERS": return RegistryHive.Users;
case "HKEY_PERFORMANCE_DATA": return RegistryHive.LocalMachine;
case "HKEY_CURRENT_CONFIG": return RegistryHive.CurrentConfig;
case "HKEY_DYN_DATA": return RegistryHive.DynData;
default: throw new System.ArgumentException(nameof(basekeyName));
}
}
public static RegistryKey OpenBaseKey(this RegistryKey key)
{
return RegistryKey.OpenBaseKey(GetRegistryHive(key), key.View);
}