C# 32位程序在64位系统下注册表操作

转载自:
1、http://www.cnblogs.com/iamlucky/p/5998510.html
2、http://www.cnblogs.com/iamlucky/p/5998086.html
3、http://www.cnblogs.com/mingmingruyuedlut/archive/2011/01/21/1941225.html

----------------------------------   我是分割线   ------------------------------------

在64位的Windows操作系统中,为了兼容32位程序的运行,64位的Windows操作系统采用重定向机制。目的是为了能让32位程序在64位的操作系统不仅能操作关键文件文夹和关键的注册表并且又要避免与64位程序冲突。
在64位的Windows操作系统上,可以运行32位的应用程序,这是通过一个叫做WOW64的模拟器来实现的。WOW64 是一个由操作系统提供的兼容性环境,它使得 32 位应用程序能够在 Windows 64 位操作系统上运行,在系统的Windows目录下,存在System32和SysWOW64两个文件夹:

  System32文件夹下存放的是64位DLL
  SysWOW64文件夹下存放的是32位DLL

同样的:

  64位的应用程序保存在Program File文件夹下
  32位的应用程序保存在Program File(X86)文件夹下

而注册表相应的也有两套。

即使指定了绝对路径,如“%windir%/System32“,根据调用程序的不同,系统会自动重定向到相应的目录。

禁止系统的重定向的解决办法是调用下面的API函数

禁用系统重定向用下面的函数:
BOOL Wow64DisableWow64FsRedirection(PVOID OldValue);

恢复系统重定向用下面的函数:
BOOL Wow64RevertWow64FsRedirection(PVOID OldValue);


下面是在C#中对这两个函数的引用:

点击(此处)折叠或打开

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

  7. 省略相关代码.......


  8. IntPtr oldWOW64State = new IntPtr();
  9. Wow64DisableWow64FsRedirection(ref oldWOW64State); // 关闭64位(文件系统)的操作转向

  10. 省略相关代码(如系统目录下的文件操作).....

  11. Wow64RevertWow64FsRedirection(oldWOW64State);    // 开启64位(文件系统)的操作转向

下面是以获取操作系统安装密匙KEY的案例:

点击(此处)折叠或打开

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Microsoft.Win32;

  7. namespace ReadProductKey
  8. {
  9.     class Program
  10.     {
  11.         static void Main(string[] args)
  12.         {
  13.             string BackupProductKeyDefault;
  14.             RegistryKey localKey = null;
  15.             try
  16.             {
  17.           //判断操作系统版本(64位\32位)打开注册表项
  18.                 localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, Environment.Is64BitOperatingSystem?RegistryView.Registry64: RegistryView.Registry32);
  19.           //得到注册表键值
  20.                 BackupProductKeyDefault = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform").GetValue("BackupProductKeyDefault", "").ToString();
  21.                 Console.WriteLine(BackupProductKeyDefault);
  22.                 Console.ReadLine();
  23.             }
  24.             catch (Exception ex)
  25.             {
  26.                 
  27.             }
  28.         }
  29.     }
  30. }

------------------------------------------------------------------------------------------------------------------------

部分原文:

我的上一篇文章已经阐述了“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位(文件系统)的操作转向


请使用浏览器的分享功能分享到微信等