C# .net 3.5 32位app操作64位操作系统的注册表

做项目的过程中需要读取和修改注册表,操作过程中发现读取的注册的注册表和实际的值不一致。

查阅网上信息了解到,64位操作系统为32位app独立设置了一个目录存放它的注册表项目

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node

32位如果调用C#自己的函数,则会默认读取32位的注册表,而不会读取64位的注册表。.net4.5之后有办法直接读取。而.net 3.5无法直接读取。只能调用win32api读取

主要用到了是RegOpenKeyEx,RegQueryKeyEx和RegSerKeyEx。

写了一个类可以直接拿去项目里面用。

using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32;

namespace ServiceTest
{
    /// <summary>
    /// An extension class to allow a registry key to allow it to get the
    /// registry in the 32 bit (Wow6432Node) or 64 bit regular registry key
    /// </summary>
    public static class RegistryWOW6432
    {
        #region Member Variables
        #region Read&Write 64bit Reg from 32bit app
        public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
        public static UIntPtr HKEY_CURRENT_USER = new UIntPtr(0x80000001u);

        [DllImport("Advapi32.dll")]
        static extern uint RegOpenKeyEx(
            UIntPtr hKey,
            string lpSubKey,
            uint ulOptions,
            int samDesired,
            out int phkResult);

        [DllImport("Advapi32.dll")]
        static extern uint RegCloseKey(int hKey);

        [DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")]
        public static extern int RegQueryValueEx(
            int hKey,
            string lpValueName,
            int lpReserved,
            ref RegistryValueKind lpType,
            StringBuilder lpData,
            ref uint lpcbData);

        [DllImport("advapi32.dll", EntryPoint = "RegSetValueEx")]
        public static extern int RegSetValueEx(
            int hKey,
            string lpValueName,
            int lpReserved,
             RegistryValueKind lpType,
            string lpData,
            int len
            );
        
      

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegQueryValueEx")]
        private static extern int RegQueryValueEx(
            int hKey,
            string lpValueName,
            int lpReserved,
            ref RegistryValueKind lpType,
            [Out] byte[] lpData,
            ref uint lpcbData);
        #endregion
        #endregion

        #region Functions
        public static string GetRegKey64(this RegistryKey inKey, String inPropertyName)
        {
            string strKey = inKey.ToString();
            string regHive = strKey.Split('\\')[0];
            string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
            return GetRegKey(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName);
        }

        public static void SetRegKey64(this RegistryKey inKey, String inPropertyName, String inPropertyValue)
        {
            string strKey = inKey.ToString();
            string regHive = strKey.Split('\\')[0];
            string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
            SetRegKey(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName,inPropertyValue);
        }

        public static string GetRegKey32(this RegistryKey inKey, String inPropertyName)
        {
            string strKey = inKey.ToString();
            string regHive = strKey.Split('\\')[0];
            string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
            return GetRegKey(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName);
           
        }

        public static void SetRegKey32(this RegistryKey inKey, String inPropertyName, String inPropertyValue)
        {
            string strKey = inKey.ToString();
            string regHive = strKey.Split('\\')[0];
            string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
            SetRegKey(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName, inPropertyValue);
        }

        public static byte[] GetRegKey64AsByteArray(this RegistryKey inKey, String inPropertyName)
        {
            string strKey = inKey.ToString();
            string regHive = strKey.Split('\\')[0];
            string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
            return GetRegKeyAsByteArray(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_64Key, inPropertyName);
        }

        public static byte[] GetRegKey32AsByteArray(this RegistryKey inKey, String inPropertyName)
        {
            string strKey = inKey.ToString();
            string regHive = strKey.Split('\\')[0];
            string regPath = strKey.Substring(strKey.IndexOf('\\') + 1);
            return GetRegKeyAsByteArray(GetRegHiveFromString(regHive), regPath, RegSAM.WOW64_32Key, inPropertyName);
        }

        private static UIntPtr GetRegHiveFromString(string inString)
        {
            if (inString == "HKEY_LOCAL_MACHINE")
                return HKEY_LOCAL_MACHINE;
            if (inString == "HKEY_CURRENT_USER")
                return HKEY_CURRENT_USER;
            return UIntPtr.Zero;
        }

        static public string GetRegKey(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)
        {
            //UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
            int hkey = 0;

            try
            {
                uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
                if (0 != lResult) return null;
                RegistryValueKind lpType = 0;
                uint lpcbData = 1024;
                StringBuilder strBuffer = new StringBuilder(1024);
                RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, strBuffer, ref lpcbData);
                string value = strBuffer.ToString();
                return value;
            }
            finally
            {
                if (0 != hkey) RegCloseKey(hkey);
            }
        }


        static public void SetRegKey(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName,string inPropertyValue)
        {
            int hkey = 0;

            try
            {
                uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.AllAccess | (int)in32or64key, out hkey);
                if (lResult != 0) return;
                RegistryValueKind lpType = RegistryValueKind.String;
                RegSetValueEx(hkey, inPropertyName, 0, lpType, inPropertyValue, inPropertyValue.Length);
            }
            finally
            {
                if (0 != hkey) RegCloseKey(hkey);
            }
        }

        
        static public byte[] GetRegKeyAsByteArray(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)
        {
            int hkey = 0;

            try
            {
                uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
                
                if (0 != lResult) return null;
                RegistryValueKind lpType = 0;
                uint lpcbData = 2048;

                // Just make a big buffer the first time
                byte[] byteBuffer = new byte[1000];
                // The first time, get the real size
                RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData);
                // Now create a correctly sized buffer
                byteBuffer = new byte[lpcbData];
                // now get the real value
                RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData);

                return byteBuffer;
            }
            finally
            {
                if (0 != hkey) RegCloseKey(hkey);
            }
        }
        #endregion

        #region Enums
        public enum RegSAM
        {
            QueryValue = 0x0001,
            SetValue = 0x0002,
            CreateSubKey = 0x0004,
            EnumerateSubKeys = 0x0008,
            Notify = 0x0010,
            CreateLink = 0x0020,
            WOW64_32Key = 0x0200,
            WOW64_64Key = 0x0100,
            WOW64_Res = 0x0300,
            Read = 0x00020019,
            Write = 0x00020006,
            Execute = 0x00020019,
            AllAccess = 0x000f003f
        }
        #endregion
    }
}

使用方法

RegistryKey localKey = Registry.LocalMachine;
string strName ="";
localKey = localKey.OpenSubKey(@"SOFTWARE\Nokia\Connectivity Server\LinkControl\SCTP");
if (localKey != null)
{
       strName = localKey.GetRegKey64("dxtSignIP")
}

localKey.SetRegKey64("dxtSignIP", "10.3.38.1");

下面是对用到的几个函数的参数说明 有兴趣的可以自己看看研究一下

RegOpenKeyEx

 LONG RegOpenKeyEx(
  HKEY hKey,
  LPCTSTR lpSubKey,
  DWORD ulOptions,
  REGSAM samDesired,
  PHKEY phkResult
);

打开一个指定的注册表项,值得注意的是注册表的键值是不区分大小写的。
hKey是主键,可以是预定义的键值,如HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USERS 这几个。
lpSubKey是子键,指向一个字符串。当这个字符串为空或这指针为NULL时,他会打开hKey的值。
ulOptions保留。
samDesired是一种权限,如常用的查询权限KEY_QUERY_VALUE,用于创建子键的KEY_CREATE_SUB_KEY,用于写的权限KEY_SET_VALUE等。
phkResult是一个句柄,就像CreateEvent一样,返回了一个打开的注册表键,用完了就用它来关闭。
返回值表示成功或失败,成功则ERROR_SUCCESS,其他则表示出了些问题,在Winerror.h中定义。

 RegCloseKey

 LONG RegCloseKey(
  HKEY hKey
);

用于关闭已经打开(RegOpenKeyEx)的或者创建出来(RegCreateKeyEx)的注册表键值的句柄。
这个操作类似closeHandle。

RegCreateKeyEx

 LONG RegCreateKeyEx(
  HKEY hKey,
  LPCTSTR lpSubKey,
  DWORD Reserved,
  LPTSTR lpClass,
  DWORD dwOptions,
  REGSAM samDesired,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  PHKEY phkResult,
  LPDWORD lpdwDisposition
);

创建一个注册表键值,如果该值已存在,则类似Open的行为。
hKey与RegOpenKeyEx相似。
lpSubKey是要创建的子键的字符串。该值不可以为NULL,也不可以含有反斜线/,而且是不区分大小写的。
Reserved保留。传入0即可。
lpClass通常设置为NULL。
dwOptions默认设置为REG_OPTION_NON_VOLATILE,另外两个值REG_OPTION_BACKUP_RESTORE和REG_OPTION_VOLATILE有特殊的含义,详细信息见MSDN。
samDesired与RegOpenKeyEx的相应参数含义一样。通常创建一个子键的行为需要Create权限,因为这个函数需要创建子键,但是他并不能设置这个子键的值,需要别的函数帮助。
lpSecurityAttributes是安全级别,传入NULL为默认级别。
phkResult是handle。用于之后的操作。
lpdwDisposition是一个传出参数,它标示了调用该函数是新建了一个子键REG_CREATED_NEW_KEY还是打开了一个原有子键REG_OPENED_EXISTING_KEY。
返回值同样是ERROR_SUCCESS表示成功,其他则表示有问题。


RegSetValueEx

 LONG RegSetValueEx(
  HKEY hKey,
  LPCTSTR lpValueName,
  DWORD Reserved,
  DWORD dwType,
   const  BYTE *  lpData,
  DWORD cbData
);

创建了子键,需要给它赋以特定的值,该函数就是为子键赋值的。
hKey是目标键的handle。
lpValueName是子键名称。
Reserved保留,一般写0。
dwType表示值的类型,常用的有二进制REG_BINARY、DWORD类型REG_DWORD、字符串REG_SZ等。
lpData是值内容。
cbData是值内容的大小,sizeof即可,不过当是字符串的时候,记得加1,来表示结尾符。

RegQueryValueEx

 LONG RegQueryValueEx(
  HKEY hKey,
  LPCTSTR lpValueName,
  LPDWORD lpReserved,
  LPDWORD lpType,
  LPBYTE lpData,
  LPDWORD lpcbData
);

我们要读一个已经打开的键的值的时候,就需要这个函数。
hKey是目标键的handle。
lpValueName是子键名称。
lpReserved保留,一般写0。
lpType是值类型,同RegSetValueEx的类型含义相同。但是他是传出的,这时就有一个小技巧,当我们不知道一个键的值类型时,我们可以用这个参数第一次读出值的类型,后两个参数传入NULL和大小,这时读出了值的类型和值的大小,这样在第二次想确切的读出值的内容的时候,就可以分配恰好可用的空间。
lpData是传出参数,用于读出的数据。
lpcbData是传出参数的长度。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值