C# 32各程序和64个程序读\写注册表的分。C# 32员程序访问64员系统注册表。

  用C#实现注册表的朗诵\描绘是一律码特别易之事体,在斯不做详细的教授。

  我的高达一致篇稿子曾阐述了“32员程序和64位程序在64号平台上读\描绘注册表的分”,那么连下去就要对上篇所留下来的一个问题:32员程序如何看64员系统注册表(即:64位程序所走访的注册表位置)。

  用C#操作注册表主要使用的少只函数为(已经渗透及下的实例程序中,注:要引入Microsoft.Win32命名空间):

  我们曾清楚:

      1:读取键值–>Registry.LocalMachine.OpenSubKey(“..Key的路程径…”,
true),这里的第2只bool类型的参数含义为:标志打开的键值是否可转移(即:是否可就此SetValue()给键赋值),然后调用GetValue()方法就能将键值读取出来。

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

      2:写副键值–>Registry.LocalMachine.CreateSubKey(“..Key的路程径…”),然后调用SetValue()写副键值。

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

  这里主要讲解一下32各类程序与64各类程序于64各项平台及宣读\写注册表的界别【注:32员程序是–>Build的Platform
target为X86;64位程序–>Build的Platform
target为X64;并且VS2010于默认的状态下吧X86编译环境(即:32各项)】

  那么只要促成32吧顺序访问64员注册表信息,还要懂得如下概念:1:文件系统转向。2:注册表重定向(转向)。3:注册表反射。

  简要复述一下反驳基础:微软为吃32位程序不举行其他改动就能够运行在64之操作系统及,添加了一个分外主要之WOW64子系统来贯彻此职能,WOW64凡Windows-32-on-Windows-64之简称,从总体上来说,WOW64是同样仿基于用户模式之动态链接库,它可以将32位应用程序的产生的吩咐翻译成64各类系统可领之格式,即:WOW
层处理诸如在 32 位和 64 位模式中切换处理器以及拟 32
位系统的作业。

    ①:文件系统转向

  32位与64位特点之蝇头只重大表现方面呢:文件系统与注册表

    32
位进程不能够加载64个Dll,64个过程也无可以加载32员Dll。Windows的系统目录包含了颇具安装之应用程序和它的Dll文件,根据我们所述
的平整,

      文件系统:32各项过程不能够加载64各Dll,64各过程也不可以加载32个Dll。

    它应为分为给64号应用程序的目录和吃32各类应用程序的目。如果非这么,我们便无法区分32各与64各之Dll文件。对于64个应用程序,其
文件一般被

      注册表:为了以防注册表键冲突,64各项机器注册表信息分成了片只有。一部分是专门被64个系统(即:64员程序)访问的,另一样部分是特意让32位系统(即:32号程序)访问的,放在Wow6432Node下面。(Wow6432Node这个节
点存在于HKEY_LOCAL_MACHINE和HKEY_CURRENT_USER下面)

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

  既然知道了注册表信息分成了点滴部分,那么尽管可想到:用32各类程序及64各项程序去操作注册表的时候会操作不同职务的注册表信息。下面例子可以充分证明这种说法。

    C:\program files
(x86)下面。如果我们用32位程序去访问%windir%\system32,不管我们为此硬编码还是其它的方,系统都见面自行地让咱们

 

    转向到%windir%\syswow64下面。这种转化对每个32员应用程序默认都是打开的。但是这种转化对我们的话并无总是用之。那么我们可在

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

 namespace OperateRegistrationTable 
{ 
     class Programe
     {
         static void Main(string[] args)
         {
             OperatingRegistryKey();
         }

         public static void OperatingRegistryKey()
         {
             string keyValue = string.Empty;
             try
             {
                 //向注册表中写信息
                 using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\EricSun\MyTestKey", true))
                 {
                     if (key == null)
                    {
                         using (RegistryKey myKey = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\EricSun\MyTestKey"))
                         {
                             myKey.SetValue("MyKeyName", "Hello EricSun." + DateTime.Now.ToString());
                         }
                     }
                     else
                     {
                         key.SetValue("MyKeyName", "Hello EricSun." + DateTime.Now.ToString());
                     }
                 }

                 //读取注册表信息
                 using (RegistryKey currentKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\EricSun\MyTestKey", false))
                 {
                     if (currentKey == null)
                     {
                         Console.WriteLine("Hello EricSun, The Key you tried to open doesn't exist.");
                     }
                     else
                     {
                         keyValue = currentKey.GetValue("MyKeyName").ToString();
                         Console.WriteLine("The Key Value is: {0}", keyValue);
                     }
                 }
             }
             catch (Exception ex)
             { }
         }
     }
 }

    C#内部调用相关的API来关闭与开辟这种转化。常用的函数有3个:

  

        Wow64DisableWow64FsRedirection(关闭系统转
向),

  将此段程序在X86(32各类)平台下编译、运行,会发觉于注册表的WOW6432Node节点下创办了子键:EricSun\MyTestKey,并且填充了键MyKeyName的价(用时间再说区分其值),而于SoftWare的首先层子节点受到并不曾发现此EricSun。可以规定32各项程序是操作注册表信息是身处WOW6432Node节点下的

        Wow64RevertWow64FsRedirection(打开系统转向),

  若我们本着这段先后不举行其他修改,在X64(或Any
Cpu)的平台下编译、运行吧,会意识以注册表的SoftWare节点的首先层子节点受到创造有了EricSun节点(并当这个节点下创造相应的注册表信息),然后我们就此同样的主次去读注册表的早晚啊会发现他们读取的地方不同(以程序中之时间信息加以区分)

        Wow64EnableWow64FsRedirection(打
开系统转向)。

  总结:X64,(或者Any Cpu)
Platform下的程序会操作64各机器存放注册表位置的注册表信息,X86
Platform下的程序会操作32员机器存放注册表位置的注册表信息(即:WOW6432Node节点下的注册表信息)

    但是Wow64EnableWow64FsRedirection在嵌套使用的上不可靠,所以普通用地方的
Wow64RevertWow64FsRedirection来打开文件系统转向

转载于:http://www.cnblogs.com/mingmingruyuedlut/archive/2011/01/20/1940371.html

    功能。在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.InteropServices】

  下面请圈代码示例

 

  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各类程序所访问的注册表位置)。

相关文章