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

原文: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.InteropServices】

  下面请看代码示例


1 using System;
2  using System.Collections.Generic;
3  using System.Linq;
4  using System.Text;
5  using Microsoft.Win32;
6  using System.Runtime.InteropServices;
7
8  namespace OperateRegistrationTable
9 {
10 class Programe
11 {
12 static void Main(string[] args)
13 {
14 string myParentKeyName = "HKEY_LOCAL_MACHINE";
15 string mySubKeyName = @"SOFTWARE\EricSun\MyTestKey";
16 string myKeyName = "MyKeyName";
17
18 string value = string.Empty;
19 value = Utility.Get64BitRegistryKey(myParentKeyName, mySubKeyName, myKeyName);
20 Console.WriteLine("The Value is: {0}", value);
21 }
22 }
23
24 public class Utility
25 {
26 #region 32位程序读写64注册表
27
28 static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)0x80000000;
29 static UIntPtr HKEY_CURRENT_USER = (UIntPtr)0x80000001;
30 static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
31 static UIntPtr HKEY_USERS = (UIntPtr)0x80000003;
32 static UIntPtr HKEY_CURRENT_CONFIG = (UIntPtr)0x80000005;
33
34 // 关闭64位(文件系统)的操作转向
35   [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
36 public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
37 // 开启64位(文件系统)的操作转向
38   [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
39 public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
40
41 // 获取操作Key值句柄
42   [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
43 public static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, 

                                  int samDesired, out IntPtr phkResult);
44 //关闭注册表转向(禁用特定项的注册表反射)
45 [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
46 public static extern long RegDisableReflectionKey(IntPtr hKey);
47 //使能注册表转向(开启特定项的注册表反射)
48 [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
49 public static extern long RegEnableReflectionKey(IntPtr hKey);
50 //获取Key值(即:Key值句柄所标志的Key对象的值)
51 [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
52 private static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int lpReserved,
53 out uint lpType, System.Text.StringBuilder lpData,
54 ref uint lpcbData);
55
56 private static UIntPtr TransferKeyName(string keyName)
57 {
58 switch (keyName)
59 {
60 case "HKEY_CLASSES_ROOT":
61 return HKEY_CLASSES_ROOT;
62 case "HKEY_CURRENT_USER":
63 return HKEY_CURRENT_USER;
64 case "HKEY_LOCAL_MACHINE":
65 return HKEY_LOCAL_MACHINE;
66 case "HKEY_USERS":
67 return HKEY_USERS;
68 case "HKEY_CURRENT_CONFIG":
69 return HKEY_CURRENT_CONFIG;
70 }
71
72 return HKEY_CLASSES_ROOT;
73 }
74
75 public static string Get64BitRegistryKey(string parentKeyName, string subKeyName, string keyName)
76 {
77 int KEY_QUERY_VALUE = (0x0001);
78 int KEY_WOW64_64KEY = (0x0100);
79 int KEY_ALL_WOW64 = (KEY_QUERY_VALUE | KEY_WOW64_64KEY);
80
81 try
82 {
83 //将Windows注册表主键名转化成为不带正负号的整形句柄(与平台是32或者64位有关)
84 UIntPtr hKey = TransferKeyName(parentKeyName);
85
86 //声明将要获取Key值的句柄
87 IntPtr pHKey = IntPtr.Zero;
88
89 //记录读取到的Key值
90 StringBuilder result = new StringBuilder("".PadLeft(1024));
91 uint resultSize = 1024;
92 uint lpType = 0;
93
94 //关闭文件系统转向
95 IntPtr oldWOW64State = new IntPtr();
96 if (Wow64DisableWow64FsRedirection(ref oldWOW64State))
97 {
98 //获得操作Key值的句柄
99 RegOpenKeyEx(hKey, subKeyName, 0, KEY_ALL_WOW64, out pHKey);
100
101 //关闭注册表转向(禁止特定项的注册表反射)
102 RegDisableReflectionKey(pHKey);
103
104 //获取访问的Key值
105 RegQueryValueEx(pHKey, keyName, 0, out lpType, result, ref resultSize);
106
107 //打开注册表转向(开启特定项的注册表反射)
108 RegEnableReflectionKey(pHKey);
109 }
110
111 //打开文件系统转向
112 Wow64RevertWow64FsRedirection(oldWOW64State);
113
114 //返回Key值
115 return result.ToString().Trim();
116 }
117 catch (Exception ex)
118 {
119 return null;
120 }
121 }
122
123 #endregion
124 }
125 }

Get64BitRegistryKey函数的三个参数分别代表:主键名(如:HKEY_LOCAL_MACHINE等),子键名,Key名,返回的是Key的Value(64位系统注册表的键值),通过上面的方法就完全可以实现用32程序访问64位系统注册表(即:64位程序所访问的注册表位置)。

时间: 2024-10-31 01:19:03

C# 32位程序访问64位系统注册表的相关文章

使用.netFx4.0提供的方法解决32位程序访问64位系统的64位注册表

原文:使用.netFx4.0提供的方法解决32位程序访问64位系统的64位注册表   我们知道目标平台是32位的程序运行在64位的系统上,去访问部分注册表的时候系统自动重定向到win32node节点对应的项去了.但是做过安装程序开发人员可能遇到过"需要去掉重定向"的问题,即直接访问64位程序的注册表. 网上有很多winAPI的方法,关闭注册表的重定向稍微复杂.(关闭文件系统的重定向稍微简单些,搬过来就可以用:关闭注册表的重定向我现在没看懂.) 我这里提供的方法不需要关闭重定向,也不需要

VB的32位程序在64位系统中出现文件和注册表自动转向的解决方法_vb

通常用VB 写的程序在32位系统上可以正常的运行,但到了64位系统中虽然可以运行但是无法修改OEM信息.经过查找原因可以发现,当我们在访问文件夹"SYSTEM32"的时候系统会自动转向到文件夹"SYSWOW64"下,当我们在访问某些注册表键值的时候,和文件转向类似,系统也会自动地把程序的访问转向到Wow6432Node下面. 先来谈谈文件系统的转向,查找了一些资料,并没有VB相关的资料,但是可以查到2个相关函数:Wow64DisableWow64FsRedirect

c++-开发32位程序和64位程序有什么区别?假设用C++开发

问题描述 开发32位程序和64位程序有什么区别?假设用C++开发 假设现要开发一个win程序,用C++语言,那么开发我32bit程序跟开发64bit程序有什么区别? 解决方案 你是问开发有什么不同,ok,其实google一下答案就有了. 1. 首先数据类型不一样 在32位平台整型啊,指针啊都是32位的,到64位平台就是64位了,你要注意这个区别,比如溢出. 还有一些数据结构变化了,比如time_t,你的小心. 浮点数的结构也在32和64也不太一样 2. 数据转换发生了变化,比如在32位平台做以下

Windows 7系统迁移指南——从32位过渡到64位

Windows--包括http://www.aliyun.com/zixun/aggregation/34065.html">WindowsXP,Vista,Windows 7以及该操作系统的服务器版本--已经从32位过渡到了64位.硬件制造商有足够的时间为其产品提供32/64位的驱动程序. 事实上,我们现在买到的几乎每个扫描仪,打印机,视频摄像头或其他硬件设备都能提供这两种平台的驱动.因此如果我们添置一套新设备时无需担心兼容问题.但是如果我们要将以前购买的打印机,扫描仪或摄像头进行迁移,

关于32位系统和64位系统运行asp。net程序的兼容性问题。

问题描述 我现在做了一个asp.net网站,用的C#.vs2008开发环境,操作系统是windowsserver2008x32.数据库:oracle10g.运行一切正常.现在客户换了一台服务器,装windowsserver2008X64版本.不知道我的这个网站部署到64位的系统是有问题没有.如果有兼容问题,该怎么解决. 解决方案 解决方案二:如果程序是纯.NET写的,完全没有问题.如果程序使用了32bit的dll或者activex组件,那么需要把程序集编译成32bit.解决方案三:网页中有一个f

Win7 32位系统和64位系统有什么区别

  首先,相信选择64位Windows7的网友中很有大比例是内存大于或等于4GB的.在32位Windows7下,可能会显示内存可使用3.25G,这让很多网友感到不安.没错,可寻址的内存空间确实是32位Windows7和64位Windows7最为显著的特点. 32位的CPU(准确的说是运行在32位模式下的CPU)只能寻址最大4GB的内存,受制于此,32位的操作系统也只能识别最大4GB的内存,由于在系统中,除了内存之外,还有很多存储设备,因此,真正可以利用的内存空间肯定小于4GB,也就是我们看到的系

iOS上应用如何兼容32位系统和64位系统

      在苹果推出iPhone5S时,64位的应用就走到了眼前.当时就看见苹果官方资料宣布iOS7.x的SDK支持了64位的应用,而且内置的应用都已经是64位.       我记得自己刚刚接触电脑时还有16位的系统,指针的寻址范围还是16位的.当年用TurboC时,还要根据应用的大小选择是tiny模式还是其他.后来很长一段时间使用32位的模型编程,4G是牢牢记住的一个边界条件.而现在,64位走到了眼前.       就如同16位转向32位一样,硬件肯定是最先推出的,SDK也会跟进,然后各种第

Windows 7 32位系统和64位系统有区别是什么

选择64位Windows7系统是因为很内存大于或等于4GB的.在32位Windows7下,可能会显示内存可使用3.XXG,可寻址的内存空间是32位Windows7和64位Windows7最为显著的特点.32位的CPU(准确的说是运行在32位模式下的CPU)只能寻址最大4GB的内存,受制于此,32位的操作系统也只能识别最大4GB的内存,由于在系统中,除了内存之外,还有很多存储设备,因此,真正可以利用的内存空间肯定小于4GB,也就是我们看到的系统属性中显示的3.xxG.但64位CPU则有了很大改变,

一个32位系统和64位系统的一个weblogic server 分别支持 最大的内存 和 最合理的并发量是多少

问题描述 一个32位系统和64位系统的一个weblogicserver分别支持最大的内存和最合理的并发量是多少?有没有什么行业标准值呢?假如我的系统每天有好几万用户访问,设置多少个weblogicserver合理些?希望有知道的朋友能给介绍介绍,非常感激!!! 解决方案 解决方案二:在weblogic中间件中的32位还是64位是取决于硬件支持和jdk的版本支持的.在硬件支持的条件下,32位jdk的最大进程空间是4g.64位jdk的最大进程空间理论上接近于无限大解决方案三:我也遇到个类似的问题:现