C#操作注冊表


1、微軟為了讓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下面)

2、舉例說明

首先下載了32位軟件Winrar(下載地址:http://www.winrar.com.cn/),分別在32位和64位機器上進行安裝,版本號請看截圖  

  

  通過查詢注冊表可知,Winrar的版本號在32位機器里的注冊表里的路徑Path:"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinRAR archiver ".且Key值為:"DisplayVersion"

  Winrar的版本號在32位機器里的注冊表里的路徑Path:"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WinRAR archiver ".且Key值為:"DisplayVersion"

3、現在編寫一個代碼分別進行讀取,更改,以實現C#讀取注冊表 

 寫一個注冊表類RegUtil.cs

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

namespace ToolUtils
{
    public static class RegUtil
    {
        static readonly IntPtr HKEY_CLASSES_ROOT = new IntPtr(unchecked((int)0x80000000));
        static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int)0x80000001));
        static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002));
        static readonly IntPtr HKEY_USERS = new IntPtr(unchecked((int)0x80000003));
        static readonly IntPtr HKEY_PERFORMANCE_DATA = new IntPtr(unchecked((int)0x80000004));
        static readonly IntPtr HKEY_CURRENT_CONFIG = new IntPtr(unchecked((int)0x80000005));
        static readonly IntPtr HKEY_DYN_DATA = new IntPtr(unchecked((int)0x80000006));

        // 獲取操作Key值句柄 
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegOpenKeyEx(IntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out IntPtr phkResult);

        //創建或打開Key值
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegCreateKeyEx(IntPtr hKey, string lpSubKey, int reserved, string type, int dwOptions, int REGSAM, IntPtr lpSecurityAttributes, out IntPtr phkResult,
                                                 out int lpdwDisposition);

        //關閉注冊表轉向(禁用特定項的注冊表反射)
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegDisableReflectionKey(IntPtr hKey);

        //使能注冊表轉向(開啟特定項的注冊表反射)
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int 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);

        //設置Key值
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegSetValueEx(IntPtr hKey, string lpValueName, uint unReserved, uint unType, byte[] lpData, uint dataCount);

        //關閉Key值
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegCloseKey(IntPtr hKey);

        public static IntPtr TransferKeyName(string keyName)
        {
            IntPtr ret = IntPtr.Zero;
            switch (keyName)
            {
                case "HKEY_CLASSES_ROOT":
                    ret = HKEY_CLASSES_ROOT;
                    break;
                case "HKEY_CURRENT_USER":
                    ret = HKEY_CURRENT_USER;
                    break;
                case "HKEY_LOCAL_MACHINE":
                    ret = HKEY_LOCAL_MACHINE;
                    break;
                case "HKEY_USERS":
                    ret = HKEY_USERS;
                    break;
                case "HKEY_PERFORMANCE_DATA":
                    ret = HKEY_PERFORMANCE_DATA;
                    break;
                case "HKEY_CURRENT_CONFIG":
                    ret = HKEY_CURRENT_CONFIG;
                    break;
                case "HKEY_DYN_DATA":
                    ret = HKEY_DYN_DATA;
                    break;
                default:
                    ret = HKEY_LOCAL_MACHINE;
                    break;
            }
            return ret;
        }

        /// <summary>
        /// 設置64位注冊表
        /// </summary>
        /// <param name="key"></param>
        /// <param name="subKey"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int Set64BitRegistryKey(string key, string subKey, string name, string value)
        {
            int STANDARD_RIGHTS_ALL = (0x001F0000);
            int KEY_QUERY_VALUE = (0x0001);
            int KEY_SET_VALUE = (0x0002);
            int KEY_CREATE_SUB_KEY = (0x0004);
            int KEY_ENUMERATE_SUB_KEYS = (0x0008);
            int KEY_NOTIFY = (0x0010);
            int KEY_CREATE_LINK = (0x0020);
            int SYNCHRONIZE = (0x00100000);
            int KEY_WOW64_64KEY = (0x0100);
            int REG_OPTION_NON_VOLATILE = (0x00000000);
            int KEY_ALL_ACCESS = (STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS
                                 | KEY_NOTIFY | KEY_CREATE_LINK) & (~SYNCHRONIZE);

            int ret = 0;
            try
            {
                //將Windows注冊表主鍵名轉化成為不帶正負號的整形句柄(與平台是32或者64位有關)
                IntPtr hKey = TransferKeyName(key);

                //聲明將要獲取Key值的句柄 
                IntPtr pHKey = IntPtr.Zero;

                //獲得操作Key值的句柄
                int lpdwDisposition = 0;
                ret = RegCreateKeyEx(hKey, subKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, IntPtr.Zero, out pHKey, out lpdwDisposition);
                if (ret != 0)
                {
                    Log2.Log(string.Format("Unable to create key {0} - {1}: {2}!", key, subKey, ret));
                    return ret;
                }

                //關閉注冊表轉向(禁止特定項的注冊表反射)
                RegDisableReflectionKey(pHKey);

                //設置訪問的Key值
                uint REG_SZ = 1;
                byte[] data = Encoding.Unicode.GetBytes(value);

                RegSetValueEx(pHKey, name, 0, REG_SZ, data, (uint)data.Length);

                //打開注冊表轉向(開啟特定項的注冊表反射)
                RegEnableReflectionKey(pHKey);

                RegCloseKey(pHKey);
            }
            catch (Exception ex)
            {
                Log2.Log(ex.ToString());
                return -1;
            }

            return ret;
        }

        public static void SetRegistryKey(string key, string subKey, string name, string value)
        {
            Log2.Log("SetRegistryKey start.");
            if (System.IntPtr.Size == 8)
            {
                // 寫SOFTWARE\Huawei\VirtualDesktopAgent,需要關閉注冊表重定向,再寫64位路徑的注冊表
                int ret = RegUtil.Set64BitRegistryKey(key, subKey, name, value);
                if (ret != 0)
                {
                    Log2.Log(string.Format("Failed to write Reg {0}\\{1}\\{2},return {3}", key, subKey, name, ret));
                }
            }

            try
            {
                Microsoft.Win32.Registry.SetValue(key + "\\" + subKey, name, value);
            }
            catch (Exception ex)
            {
                Log2.Log(ex.ToString());
            }

            Log2.Log("SetRegistryKey exit.");
        }

        public static string GetRegistryValue(string path, string key)
        {
            RegistryKey regkey = null;
            try
            {
                regkey = Registry.LocalMachine.OpenSubKey(path);
                if (regkey == null)
                {
                    Log2.Log("Cannot find Registry path:" + path);
                    return null;
                }

                object val = regkey.GetValue(key);
                if (val == null)
                {
                    Log2.Log("Cannot find Registry key:" + key);
                    return null;
                }

                return val.ToString();
            }
            catch (Exception ex)
            {
                Log2.Log(ex.ToString());
                return null;
            }
            finally
            {
                if (regkey != null)
                {
                    regkey.Close();
                }
            }
        }
    }
}

主函數進行操作注冊表

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Regedit
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //public const string vLanID_X86 = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";


        string Winrarpath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinRAR archiver";
        string key = "DisplayVersion";

        private void Form1_Load(object sender, EventArgs e)
        {
            //獲取注冊表值(32位和64位都可以)
            string value = Common.GetRegistryValue(Winrarpath,key);
            lb_version.Text = value;  
        }

        //改注冊表值
        private void button1_Click(object sender, EventArgs e)
        {
            string value = textBox1.Text.ToString();
            Common.SetRegistryKey("HKEY_LOCAL_MACHINE", Winrarpath, "DisPlayVersion", value);
            string newValue = Common.GetRegistryValue(Winrarpath, "DisPlayVersion");
            lb_newVersion.Text = newValue;
        }
    }
}

結果,32\64位都可以改變

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM