2010-01-11 19 views
45

Tengo un código que lee el registro y busca un valor en HKEY_LOCAL_MACHINE\Software\App\, pero cuando se ejecuta en versiones de Windows de 64 bits, el valor está por debajo de HKEY_LOCAL_MACHINE\Software\Wow6432Node\App\.Leyendo el registro y la clave Wow6432Node

¿Cuál es la mejor manera de abordar esto? ¿Necesito un instalador de 64 bits o debería volver a escribir mi código para detectar ambos lugares?

+0

¿Qué programa gestiona las claves de registro en HKEY_LOCAL_MACHINE \ Software \ App? ¿Estás tratando de leer claves de registro creadas por otro programa? – wj32

+0

Hola, no, es mi aplicación la que lee la clave, la clave está escrita en el registro por el instalador de Visual Studio 2008. –

Respuesta

46

Si marca su programa C# como x86 (y no cualquier CPU), verá HKEY_LOCAL_MACHINE\Software\Wow6432Node\App como HKEY_LOCAL_MACHINE\Software\App\.

Un programa .NET para cualquier CPU se ejecutará como un proceso de 64 bits si está instalado .NET de 64 bits. El registro de 32 bits está bajo el Wow6432Node para programas de 64 bits.

+2

@Arve: Odio ser el portador de malas noticias, pero este truco no sirve para máquinas WinXP antiguas: nuestra empresa todavía usa cientos de estas y la clave Wow6432Node no está en ellas. – jp2code

+8

La clave Wow6432Node solo existe en máquinas de 64 bits –

57

En una máquina x64, aquí es un ejemplo de cómo acceder a la vista de 32 bits del registro:

using (var view32 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, 
              RegistryView.Registry32)) 
{ 
    using (var clsid32 = view32.OpenSubKey(@"Software\Classes\CLSID\", false)) 
    { 
    // actually accessing Wow6432Node 
    } 
} 

... en comparación con ...

using (var view64 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, 
              RegistryView.Registry64)) 
{ 
    using (var clsid64 = view64.OpenSubKey(@"Software\Classes\CLSID\", true)) 
    { 
    .... 
    } 
} 
6

+ 1 a la respuesta de Wally, pero su solución funciona para .NET 4.0 y superior.

he encontrado otra solución, que también trabaja para .NET 2,0 here

#region RegHelper 
enum RegSAM 
{ 
    QueryValue = 0x0001, 
    SetValue = 0x0002, 
    CreateSubKey = 0x0004, 
    EnumerateSubKeys = 0x0008, 
    Notify = 0x0010, 
    CreateLink = 0x0020, 
    WOW64_32Key = 0x0200, 
    WOW64_64Key = 0x0100, 
    WOW64_Res = 0x0300, 
    Read = 0x00020019, 
    Write = 0x00020006, 
    Execute = 0x00020019, 
    AllAccess = 0x000f003f 
} 

static class RegHive 
{ 
    public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u); 
    public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u); 
} 

static class RegistryWOW6432 
{ 
    [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); 

    static public string GetRegKey64(UIntPtr inHive, String inKeyName, string inPropertyName) 
    { 
     return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_64Key, inPropertyName); 
    } 

    static public string GetRegKey32(UIntPtr inHive, String inKeyName, string inPropertyName) 
    { 
     return GetRegKey64(inHive, inKeyName, RegSAM.WOW64_32Key, inPropertyName); 
    } 

    static public string GetRegKey64(UIntPtr inHive, String inKeyName, RegSAM in32or64key, string inPropertyName) 
    { 
     //UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; 
     int hkey = 0; 

     try 
     { 
      uint lResult = RegOpenKeyEx(RegHive.HKEY_LOCAL_MACHINE, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey); 
      if (0 != lResult) return null; 
      uint lpType = 0; 
      uint lpcbData = 1024; 
      StringBuilder AgeBuffer = new StringBuilder(1024); 
      RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, AgeBuffer, ref lpcbData); 
      string Age = AgeBuffer.ToString(); 
      return Age; 
     } 
     finally 
     { 
      if (0 != hkey) RegCloseKey(hkey); 
     } 
    } 
} 
#endregion 

Uso:

string value64 = RegistryWOW6432.GetRegKey64(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization"); 
string value32 = RegistryWOW6432.GetRegKey32(RegHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization"); 
3

Aquí es un todo-en-una solución que cubra x32/Sistemas x64 y aplicaciones de captura instaladas en la máquina local o cuenta de usuario.

public class InstalledProgramInfo 
    { 
     public string name; 
     public string path; 
    } 

     public static InstalledProgramInfo FindInstalledApp(string findname, bool dump = false) 
    { 
     if (String.IsNullOrEmpty(findname)) return null; 

     string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; 

     RegistryHive[] keys = new RegistryHive[] { RegistryHive.CurrentUser, RegistryHive.LocalMachine }; 
     RegistryView[] views = new RegistryView[] { RegistryView.Registry32, RegistryView.Registry64 }; 

     foreach (var hive in keys) 
     { 
      foreach (var view in views) 
      { 
       RegistryKey rk = null, 
        basekey = null; 

       try 
       { 
        basekey = RegistryKey.OpenBaseKey(hive, view); 
        rk = basekey.OpenSubKey(uninstallKey); 
       } 
       catch (Exception ex) { continue; } 

       if (basekey == null || rk == null) 
        continue; 

       if (rk == null) 
       { 
        if (dump) Console.WriteLine("ERROR: failed to open subkey '{0}'", uninstallKey); 
        return null; 
       } 

       if (dump) Console.WriteLine("Reading registry at {0}", rk.ToString()); 

       foreach (string skName in rk.GetSubKeyNames()) 
       { 
        try 
        { 
         RegistryKey sk = rk.OpenSubKey(skName); 
         if (sk == null) continue; 

         object skname = sk.GetValue("DisplayName"); 

         object skpath = sk.GetValue("InstallLocation"); 
         if (skpath == null) 
         { 
          skpath = sk.GetValue("UninstallString"); 
          if (skpath == null) continue; 
          FileInfo fi = new FileInfo(skpath.ToString()); 
          skpath = fi.Directory.FullName; 
         } 

         if (skname == null || skpath == null) continue; 

         string thisname = skname.ToString(); 
         string thispath = skpath.ToString(); 

         if (dump) Console.WriteLine("{0}: {1}", thisname, thispath); 

         if (!thisname.Equals(findname, StringComparison.CurrentCultureIgnoreCase)) 
          continue; 

         InstalledProgramInfo inf = new InstalledProgramInfo(); 
         inf.name = thisname; 
         inf.path = thispath; 

         return inf; 
        } 
        catch (Exception ex) 
        { 
         // todo 
        } 
       }     
      } // view 
     } // hive 

     return null; 
    } 
Cuestiones relacionadas