2009-09-24 5 views
6

Я нахожу странное поведение с модулем .NET, обращаясь к Windows Registry, используя класс RegistryKey.Доступ к реестру Windows с использованием .NET?

Например, я написал .NET-модуль testcom.dll, который обращается к реестру. Этот файл testcom.dll используется как для 32-разрядного приложения, так и для 64-разрядного приложения. Мое требование - получить значение regkey (путь HKEY_LOCAL_MACHINE\SOFTWARE\Test\MyParameters и имя ключа Age). Этот ключ «Возраст» будет находиться в 32-битном реестре на 32-битных машинах и 64-разрядном реестре (не WOW64) на 64-битных машинах.

На 64-битной машине, когда 32-разрядное приложение использует testcom.dll, поиск ключа «Возраст» выполняется в реестре WOW64. Когда 64-разрядное приложение использует testcom.dll, поиск ключа «Возраст» выполняется в 64-разрядном реестре.

Мое требование состоит в том, чтобы прочитать ключ в 64-битном реестре на 64-разрядных машинах, независимо от того, какое приложение использует файл testcom.dll. Как я могу это сделать?

+0

Thats odd. Когда я однажды написал приложение, которое искал ключи и значения в реестре, мне пришлось вручную изменить путь для 32-разрядных ключей приложения при работе в 64-разрядной ОС. Не могли бы вы разместить какой-нибудь код? Чтобы узнать, отличается ли мой метод загрузки ключей от моего? –

+0

Также приложение было 32-битным приложением. По умолчанию он не искал WOW64. –

ответ

4

У меня была аналогичная проблема, и лучший ответ, который я нашел, чтобы возвратиться к функции Win32 реестра (например, RegOpenKeyEx) и передать в соответствующие Registry Key Security and Access Rights, в частности OR'ing параметр samDesired с KEY_WOW64_64KEY ,

Было ужасно, и я надеюсь, что вы услышите лучший ответ здесь.

+0

Спасибо за ответ ур. Я также надеюсь на лучшее :) –

+0

Спасибо, наконец, ответ, который, кажется, работает. – rogerdpack

2

Ответ Блэра относительно возврата к API Win32 и вызов функции RegOpenKeyEx внутри - это лучший способ достичь этого.

Windows сама будет отображать конкретные места реестра в логические виды с помощью Registry Redirector и Registry Reflection.

Вы можете прочитать больше об этом процессе в следующей статье MSDN:
32-bit and 64-bit Application Data in the Registry

Несмотря на API Win32 является лучшим способом для достижения этой цели, это возможность «жесткое кодирование» местоположение реестр, который вы хотите получить, хотя это чревато возможными проблемами (Microsoft сама не поддерживает этот метод). Вы можете прочитать об этом в этом Stack Overflow Вопрос:
How to open a WOW64 registry key from a 64-bit .NET application

В конечном счете, Win32 API, кажется, о лучшее решение (если не самый изящный) в данный момент.
Хит Стюарт от Microsoft дает следующий ответ на вопрос this MSDN Social:

К сожалению, не существует способ передать эти флаги управляемых APIs реестра под Microsoft.Win32 имен. Вы бы должны P/вызывать собственный API такой как RegCreateKeyEx, о котором вы упомянули.

Учитывайте, однако, если вам нужно хранить данные в 32- или 64-битном виде реестра.Тема реестра редиректор в MSDN есть ключи, которые перенаправляются, которые вы, вероятно, знакомы с , и тема реестра Отражение имеет ключи, в которых значения копируются между 32- и 64-битных ключей.

Если действительно вы нужны отдельные точки зрения, вы может также рассмотреть возможность включения системного реестра отражения для ваших ключей, если вы хотите оба ваши 32- и 64-разрядных приложений разделить по крайней мере, некоторые данные реестра. См. Документацию для RegEnableReflectionKey для более .

2

В следующем коде GetAge() вернет ваше значение ключа или null, если ключ не существует.

[DllImport("Advapi32.dll")] 
static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out int phkResult); 
[DllImport("Advapi32.dll")] 
static extern uint RegCloseKey(int hKey); 
[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")] 
public static extern int RegQueryValueEx(int hKey, string lpValueName, int lpReserved, ref uint lpType, System.Text.StringBuilder lpData, ref uint lpcbData); 

public const int KEY_QUERY_VALUE = 0x0001; 
public const int KEY_WOW64_64KEY = 0x0100; 

static public string GetAge() 
{ 
    string EPG_REGKEY = @"SOFTWARE\Test\MyParameters"; 
    UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; 
    int hkey = 0; 

    try 
    { 
     uint lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, EPG_REGKEY, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, out hkey); 
     if (0 != lResult) return null; 
     uint lpType = 0; 
     uint lpcbData = 1024; 
     StringBuilder AgeBuffer = new StringBuilder(1024); 
     RegQueryValueEx(hkey, "Age", 0, ref lpType, AgeBuffer, ref lpcbData); 
     string Age = AgeBuffer.ToString(); 
     return Age; 
    } 
    finally 
    { 
     if (0 != hkey) RegCloseKey(hkey); 
    } 
} 
9

Если вы можете изменить целевую версию .NET для v4, то вы можете использовать новую функцию OpenBaseKey например,

RegistryKey registryKey; 
if (Environment.Is64BitOperatingSystem == true) 
{ 
    registryKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); 
} 
else 
{ 
    registryKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^