C# 32位程序访问64位系统注册表

  我的上一篇小说已经演讲了“32位程序和64位程序在64位平台上读\写注册表的分别”,那么接下去就要回答上篇所留下来的一个题目:32位程序如何访问64位系统注册表(即:64位程序所走访的注册表地点)。

  我们已经通晓:

    ①:本机格局 64
位程序运行在纯格局下,并且访问键和存储在偏下注册表子键中的值:HKEY_LOCAL_MACHINE\Software

    ②:32 位程序运行在 WOW64
情势下,并且访问键和值存储在偏下注册表子项中:HKEY_LOCAL_MACHINE\Software\WOW6432nod

  那么要落到实处32为顺序访问64位注册表音讯,还要领悟如下概念:1:文件系统转向。2:注册表重定向(转向)。3:注册表反射。

    ①:文件系统转向

    32
位进度不可能加载64位Dll,64位进程也不得以加载32位Dll。Windows的系统目录包括了所有安装的应用程序和它们的Dll文件,根据大家所述
的条条框框,

    它应该被分为给64位应用程序的目录和给32位应用程序的目录。即便不那样,我们就无法区分32位和64位的Dll文件。对于64位应用程序,其
文件一般被

    放在%windir%\system32和%programfiles%(比如:c:\program
files)。对于32位应用程序,其文件一般在%windir%\syswow64和

    C:\program files
(x86)上面。如若我们用32位程序去访问%windir%\system32,不管咱们用硬编码仍然其余的格局,系统都会活动地给我们

    转向到%windir%\syswow64下边。那种转化对于每个32位应用程序默认都是打开的。不过那种转化对于大家来说并不总是须求的。那么大家可以在

    C#里头调用相关的API来关闭和开拓这种转化。常用的函数有3个:

        Wow64DisableWow64FsRedirection(关闭系统转
向),

        Wow64RevertWow64FsRedirection(打开系统转向),

        Wow64EnableWow64FsRedirection(打
开系统转向)。

    可是Wow64EnableWow64FsRedirection在嵌套使用的时候不可依赖,所以平日用地点的
Wow64RevertWow64FsRedirection来开辟文件系统转向

    功能。在C#中,大家可以运用DllImport直接调用那七个函数。

    ②:注册表重定向(转向)

    若要支持的 32 位和 64 位 COM
注册和顺序共存状态,WOW64 子系统提供 32
位程序采纳的注册表的另一个视图。在 WOW64 子系统运用注册表

    重定向截获位级其他注册表调用。注册表重定向仍是可以够有限支撑登记表调用被定向到在注册表中科学的分支。

    当大家设置新程序或 Windows x64
版的微处理器上运行程序时,所做的 64 位程序的注册表调用访问
HKEY_LOCAL_MACHINE\Software 注册表子键

    不重定向。WOW64 截获由 32
位程序的登记表调用到 HKEY_LOCAL_MACHINE\Software,然后将它们重定向到

    HKEY_LOCAL_MACHINE\Software\WOW6432node
子键。 通过重定向仅 32 位程序调用,WOW64
可确保程序始终写入相应的登记表子键。

    注册表重定向不必要程序代码修改,和此进程是对用户透明。

    ③:注册表反射

    反射使五个一样的注册表,以支撑同时拓展的本机和
WOW64 操作的大体副本的存在,

    打开注册表的 64
位节在颇具时间和注册表反射提供了一种容纳 32 位的实时方法。

  不难的摸底了那些,下面说一下具体的兑现步骤:

    关闭64位(文件系统)的操作转向

      得到操作Key值的句柄

        关闭注册表转向(禁止特定项的注册表反射)

      获取访问的Key值

        打开注册表转向(开启特定项的注册表反射)

    开启64位(文件系统)的操作转向

  【注:由于大家在程序中用了DllImport,所以要引入命名空间:System.Runtime.Interop瑟维斯(Service)s】

  上面请看代码示例

 

  using System;  
  using System.Collections.Generic;  
  using System.Linq;  
  using System.Text;  
  using Microsoft.Win32;  
  using System.Runtime.InteropServices;  

  namespace OperateRegistrationTable  
 { 
     class Programe 
     { 
         static void Main(string[] args) 
         { 
             string myParentKeyName = "HKEY_LOCAL_MACHINE"; 
             string mySubKeyName = @"SOFTWARE\EricSun\MyTestKey"; 
             string myKeyName = "MyKeyName"; 

             string value = string.Empty; 
             value = Utility.Get64BitRegistryKey(myParentKeyName, mySubKeyName, myKeyName); 
             Console.WriteLine("The Value is: {0}", value); 
         } 
     } 

     public class Utility 
     { 
         #region 32位程序读写64注册表 

         static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)0x80000000; 
         static UIntPtr HKEY_CURRENT_USER = (UIntPtr)0x80000001; 
         static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; 
         static UIntPtr HKEY_USERS = (UIntPtr)0x80000003; 
         static UIntPtr HKEY_CURRENT_CONFIG = (UIntPtr)0x80000005; 

         // 关闭64位(文件系统)的操作转向 
          [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
         public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr); 
         // 开启64位(文件系统)的操作转向 
          [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
         public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);     

         // 获取操作Key值句柄 
          [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
         public static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out IntPtr phkResult); 
         //关闭注册表转向(禁用特定项的注册表反射) 
         [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
         public static extern long RegDisableReflectionKey(IntPtr hKey); 
         //使能注册表转向(开启特定项的注册表反射) 
         [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
         public static extern long RegEnableReflectionKey(IntPtr hKey); 
         //获取Key值(即:Key值句柄所标志的Key对象的值) 
         [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
         private static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int lpReserved, 
                                                   out uint lpType, System.Text.StringBuilder lpData, 
                                                   ref uint lpcbData); 

         private static UIntPtr TransferKeyName(string keyName) 
         { 
             switch (keyName) 
             { 
                 case "HKEY_CLASSES_ROOT": 
                     return HKEY_CLASSES_ROOT; 
                 case "HKEY_CURRENT_USER": 
                     return HKEY_CURRENT_USER; 
                 case "HKEY_LOCAL_MACHINE": 
                     return HKEY_LOCAL_MACHINE; 
                 case "HKEY_USERS": 
                     return HKEY_USERS; 
                 case "HKEY_CURRENT_CONFIG": 
                     return HKEY_CURRENT_CONFIG; 
             } 

             return HKEY_CLASSES_ROOT; 
         } 

         public static string Get64BitRegistryKey(string parentKeyName, string subKeyName, string keyName) 
         { 
             int KEY_QUERY_VALUE = (0x0001); 
             int KEY_WOW64_64KEY = (0x0100); 
             int KEY_ALL_WOW64 = (KEY_QUERY_VALUE | KEY_WOW64_64KEY); 

             try 
             { 
                 //将Windows注册表主键名转化成为不带正负号的整形句柄(与平台是32或者64位有关) 
                 UIntPtr hKey = TransferKeyName(parentKeyName); 

                 //声明将要获取Key值的句柄 
                 IntPtr pHKey = IntPtr.Zero; 

                 //记录读取到的Key值 
                 StringBuilder result = new StringBuilder("".PadLeft(1024)); 
                 uint resultSize = 1024; 
                 uint lpType = 0; 

                 //关闭文件系统转向  
                 IntPtr oldWOW64State = new IntPtr(); 
                 if (Wow64DisableWow64FsRedirection(ref oldWOW64State)) 
                 { 
                     //获得操作Key值的句柄 
                     RegOpenKeyEx(hKey, subKeyName, 0, KEY_ALL_WOW64, out pHKey);

                     //关闭注册表转向(禁止特定项的注册表反射)
                     RegDisableReflectionKey(pHKey);

                     //获取访问的Key值
                     RegQueryValueEx(pHKey, keyName, 0, out lpType, result, ref resultSize);

                     //打开注册表转向(开启特定项的注册表反射)
                     RegEnableReflectionKey(pHKey);
                 }

                 //打开文件系统转向
                 Wow64RevertWow64FsRedirection(oldWOW64State);

                 //返回Key值
                 return result.ToString().Trim();
             }
             catch (Exception ex)
             {
                 return null;
             }
         }

         #endregion
     }
 }

  

Get64BitRegistryKey函数的三个参数分别代表:主键名(如:HKEY_LOCAL_MACHINE等),子键名,Key名,重回的是Key的Value(64位系统注册表的键值),通过上面的主意就全盘可以兑现用32主次访问64位系统注册表(即:64位程序所访问的注册表地点)。