C#解决获取注册表为空或null的方法,32位程序与64位程序读\写注册表的区别

用C#实现注册表的读\写是一件很容易的事情,在此不做详细的讲解。

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

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

微软为了让32位程序不做任何修改就能运行在64的操作系统上,添加了一个十分重要的WOW64子系统来实现这个功能,WOW64是Windows-32-on-Windows-64的简称,从总体上来说,WOW64是一套基于用户模式的动态链接库,它可以把32位应用程序的发出的命令翻译成64位系统可以接受的格式,即:WOW 层处理诸如在 32 位和 64 位模式之间切换处理器以及模拟 32 位系统的事务。

  32位与64位特点的两个重要表现方面为:文件系统与注册表

      文件系统:32位进程不能加载64位Dll,64位进程也不可以加载32位Dll。

      注册表:为了防止注册表键冲突,64位机器注册表信息分成了两个部分。一部分是专门给64位系统(即:64位程序)访问的,另一部分是专门给32位系统(即:32位程序)访问的,放在Wow6432Node下面。(Wow6432Node这个节 点存在于HKEY_LOCAL_MACHINE和HKEY_CURRENT_USER下面)

  既然知道了注册表信息分成了两部分,那么就可以想到:用32位程序和64位程序去操作注册表的时候会操作不同位置的注册表信息。下面例子可以充分证明这种说法。

    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
    }

那么如何调用呢?

private void button2_Click(object sender, EventArgs e)
        {
                        
            string myParentKeyName = "HKEY_LOCAL_MACHINE";
            string mySubKeyName = @"SOFTWARE\Microsoft\Internet Explorer";
            string myKeyName = "Version";

            string value = string.Empty;
            value = Utility.Get64BitRegistryKey(myParentKeyName, mySubKeyName, myKeyName);
            MessageBox.Show(value);


        }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wuhanwhite

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值