C # Получить BaseKey от RegistryKey - PullRequest
       39

C # Получить BaseKey от RegistryKey

1 голос
/ 22 октября 2019

У меня есть открытый раздел реестра, например, HKEY_CURRENT_USER \ SOFTWARE \ Microsoft. Как из него извлечь Базовый ключ реестра или куст реестра?

Метод 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);

Это работает, но мне кажется, что должно быть лучшее решение.

Может быть, вы знаете другое решение?

Ответы [ 2 ]

1 голос
/ 22 октября 2019

Вы находитесь на правильном пути и делаете все, что можете.

Класс registry - это просто оболочка для win32 API , здесь нет настоящей магии, которая работает на string pathsв реестр и ульи .

Еще несколько ссылок:

  • С документацией можно ознакомиться здесь, RegistryKey Class

  • Глубокое погружение в исходный код здесь, registrykey.cs

  • API-интерфейс реестра Win32 , добавленный madreflection здесь, winreg.h header

Как вы уже отметили, более простого способа достичь желаемых целей не существует

0 голосов
/ 24 октября 2019

@ TheGeneral, спасибо за ссылку на исходный код. В registry.cs я нашел метод, который делает то, что мне нужно. К сожалению, это закрытый метод , и нам нужно переписать его еще раз в нашем проекте:

Решение Microsoft:

// 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);
}
...