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位都可以改變