我們知道目標平台是32位的程序運行在64位的系統上,去訪問部分注冊表的時候系統自動重定向到win32node節點對應的項去了。但是做過安裝程序開發人員可能遇到過“需要去掉重定向”的問題,即直接訪問64位程序的注冊表。
網上有很多winAPI的方法,關閉注冊表的重定向稍微復雜。(關閉文件系統的重定向稍微簡單些,搬過來就可以用;關閉注冊表的重定向我現在沒看懂。)
我這里提供的方法不需要關閉重定向,也不需要用winAPI,操作起來方便了許多。具體如下:
第一個方法是獲得根節點的句柄,常數是固定的。
static IntPtr GetHiveHandle(RegistryHive hive) { IntPtr preexistingHandle = IntPtr.Zero; IntPtr HKEY_CLASSES_ROOT = new IntPtr(-2147483648); IntPtr HKEY_CURRENT_USER = new IntPtr(-2147483647); IntPtr HKEY_LOCAL_MACHINE = new IntPtr(-2147483646); IntPtr HKEY_USERS = new IntPtr(-2147483645); IntPtr HKEY_PERFORMANCE_DATA = new IntPtr(-2147483644); IntPtr HKEY_CURRENT_CONFIG = new IntPtr(-2147483643); IntPtr HKEY_DYN_DATA = new IntPtr(-2147483642); switch (hive) { case RegistryHive.ClassesRoot: preexistingHandle = HKEY_CLASSES_ROOT; break; case RegistryHive.CurrentUser: preexistingHandle = HKEY_CURRENT_USER; break; case RegistryHive.LocalMachine: preexistingHandle = HKEY_LOCAL_MACHINE; break; case RegistryHive.Users: preexistingHandle = HKEY_USERS; break; case RegistryHive.PerformanceData: preexistingHandle = HKEY_PERFORMANCE_DATA; break; case RegistryHive.CurrentConfig: preexistingHandle = HKEY_CURRENT_CONFIG; break; case RegistryHive.DynData: preexistingHandle = HKEY_DYN_DATA; break; } return preexistingHandle; } /// <summary> /// 用於32位程序訪問64位注冊表 /// </summary> /// <param name="hive">根級別的名稱</param> /// <param name="keyName">不包括根級別的名稱</param> /// <param name="valueName">項名稱</param> /// <param name="view">注冊表視圖</param> /// <returns>值</returns> static object GetValueWithRegView(RegistryHive hive, string keyName, string valueName, RegistryView view) { SafeRegistryHandle handle = new SafeRegistryHandle(GetHiveHandle(hive), true);//獲得根節點的安全句柄 RegistryKey subkey = RegistryKey.FromHandle(handle, view).OpenSubKey(keyName);//獲得要訪問的鍵 RegistryKey key = RegistryKey.FromHandle(subkey.Handle, view);//根據鍵的句柄和視圖獲得要訪問的鍵 return key.GetValue(valueName);//獲得鍵下指定項的值 } /// <summary> /// 用於32位的程序設置64位的注冊表 /// </summary> /// <param name="hive">根級別的名稱</param> /// <param name="keyName">不包括根級別的名稱</param> /// <param name="valueName">項名稱</param> /// <param name="value">值</param> /// <param name="kind">值類型</param> /// <param name="view">注冊表視圖</param> static void SetValueWithRegView(RegistryHive hive, string keyName, string valueName, object value, RegistryValueKind kind, RegistryView view) { SafeRegistryHandle handle = new SafeRegistryHandle(GetHiveHandle(hive), true); RegistryKey subkey = RegistryKey.FromHandle(handle, view).OpenSubKey(keyName, true);//需要寫的權限,這里的true是關鍵。0227更新 RegistryKey key = RegistryKey.FromHandle(subkey.Handle, view); key.SetValue(valueName, value, kind); }
使用這些方法需要引入Microsoft.Win32.SafeHandles;Microsoft.Win32;system;這三個命名空間。方法只提供了主干,沒有異常處理。望大家及時交流實際使用情況,不足之處請及時指出。
關於winAPI的方法可以訪問http://home.cnblogs.com/u/xuguilin/相應的文章,同時也感謝xuguilin對我的指導。據介紹dotNet框架可能需要4.0版本以上
