1. 程式人生 > >轉載:C#關閉檔案重定向,實現操作System32資料夾

轉載:C#關閉檔案重定向,實現操作System32資料夾

我們已經知道:

    ①:本機模式64位程式執行在純模式下,並且訪問鍵和儲存在以下注冊表子鍵中的值:HKEY_LOCAL_MACHINE \ Software

    ②:32位程式執行在WOW64模式下,並且訪問鍵和值儲存在以下注冊表子項中:HKEY_LOCAL_MACHINE \ Software \ WOW6432nod

  那麼要實現32為程式訪問64位登錄檔資訊,還要知道如下概念:1:檔案系統轉向0.2:登錄檔重定向(轉向)0.3:登錄檔反射。

    ①:檔案系統轉向

    32位程序不能載入64位Dll,64位程序也不可以載入32位Dll.Windows的系統目錄包含了所有安裝的應用程式和它們的Dll檔案,根據我們所述的規則,

    它應該被分為給64位應用程式的目錄和給32位應用程式的目錄。如果不這樣,我們就無法區分32位和64位的Dll檔案。對於64位應用程式,其檔案通常被

    放在%windir%\ system32和%programfiles%(比如:c:\ program files)。對於32位應用程式,其檔案通常在%windir%\ syswow64和

    C:\ program files(x86)下面。如果我們用32位程式去訪問%windir%\ system32,不管我們用硬編碼還是其他的方式,系統都會自動地給我們

    轉向到%WINDIR%\ SysWow64資料下面。這種轉向對於每個32位應用程式預設都是開啟的。但是這種轉向對於我們來說並不總是需要的。那麼我們可以在

    C#裡面呼叫相關的API來關閉和開啟這種轉向常用的函式有3個:

        Wow64DisableWow64FsRedirection(關閉系統轉向),

        Wow64RevertWow64FsRedirection(開啟系統轉向)

        Wow64EnableWow64FsRedirection(開啟系統轉向)。

    但是Wow64EnableWow64FsRedirection在巢狀使用的時候不可靠,所以通常用上面的 Wow64RevertWow64FsRedirection來開啟檔案系統轉向

    功能。在C#中,我們可以利用DllImport直接呼叫這兩個函式。

    ②:登錄檔重定向(轉向)

    若要支援的 32 位和 64 位 COM 註冊和程式共存狀態,WOW64 子系統提供 32 位程式使用的登錄檔的另一個檢視。在 WOW64 子系統使用登錄檔

    重定向截獲位級別的登錄檔呼叫。登錄檔重定向還可以確保登錄檔呼叫被定向到在登錄檔中正確的分支。 
    當我們安裝新程式或 Windows x64 版的計算機上執行程式時,所做的 64 位程式的登錄檔呼叫訪問 HKEY_LOCAL_MACHINE\Software 登錄檔子鍵

    不重定向。WOW64 截獲由 32 位程式的登錄檔呼叫到 HKEY_LOCAL_MACHINE\Software,然後將它們重定向到

    HKEY_LOCAL_MACHINE\Software\WOW6432node 子鍵。 通過重定向僅 32 位程式呼叫,WOW64 可確保程式始終寫入相應的登錄檔子鍵。

    登錄檔重定向不要求程式程式碼修改,和此過程是對使用者透明。

    ③:登錄檔反射

    反射使兩個相同的登錄檔,以支援同時進行的本機和 WOW64 操作的物理副本的存在,

    開啟登錄檔的 64 位節在所有時間和登錄檔反射提供了一種容納 32 位的實時方法。

 

  簡單的瞭解了這些,下面說一下具體的實現步驟:

    關閉64位(檔案系統)的操作轉向

      獲得操作Key值的控制代碼

        關閉登錄檔轉向(禁止特定項的登錄檔反射)

      獲取訪問的Key值

        開啟登錄檔轉向(開啟特定項的登錄檔反射)

    開啟64位(檔案系統)的操作轉向

 

  【注:由於我們在程式中用了的DllImport,所以要引入名稱空間:System.Runtime.InteropServices】

  下面請看程式碼示例

1 using System;
2  using System.Collections.Generic;
3  using System.Linq;
4  using System.Text;
5  using Microsoft.Win32;
6  using System.Runtime.InteropServices;
7 
8  namespace OperateRegistrationTable
9 {
10 class Programe
11 {
12 static void Main(string[] args)
13 {
14 string myParentKeyName = "HKEY_LOCAL_MACHINE";
15 string mySubKeyName = @"SOFTWARE\EricSun\MyTestKey";
16 string myKeyName = "MyKeyName";
17 
18 string value = string.Empty;
19 value = Utility.Get64BitRegistryKey(myParentKeyName, mySubKeyName, myKeyName);
20 Console.WriteLine("The Value is: {0}", value);
21 }
22 }
23 
24 public class Utility
25 {
26 #region 32位程式讀寫64登錄檔
27 
28 static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)0x80000000;
29 static UIntPtr HKEY_CURRENT_USER = (UIntPtr)0x80000001;
30 static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
31 static UIntPtr HKEY_USERS = (UIntPtr)0x80000003;
32 static UIntPtr HKEY_CURRENT_CONFIG = (UIntPtr)0x80000005;
33 
34 // 關閉64位(檔案系統)的操作轉向
35   [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
36 public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
37 // 開啟64位(檔案系統)的操作轉向
38   [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
39 public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr); 
40 
41 // 獲取操作Key值控制代碼
42   [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
43 public static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, 
                                  int samDesired, out IntPtr phkResult);
44 //關閉登錄檔轉向(禁用特定項的登錄檔反射)
45 [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
46 public static extern long RegDisableReflectionKey(IntPtr hKey);
47 //使能登錄檔轉向(開啟特定項的登錄檔反射)
48 [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
49 public static extern long RegEnableReflectionKey(IntPtr hKey);
50 //獲取Key值(即:Key值控制代碼所標誌的Key物件的值)
51 [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
52 private static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int lpReserved,
53 out uint lpType, System.Text.StringBuilder lpData,
54 ref uint lpcbData);
55 
56 private static UIntPtr TransferKeyName(string keyName)
57 {
58 switch (keyName)
59 {
60 case "HKEY_CLASSES_ROOT":
61 return HKEY_CLASSES_ROOT;
62 case "HKEY_CURRENT_USER":
63 return HKEY_CURRENT_USER;
64 case "HKEY_LOCAL_MACHINE":
65 return HKEY_LOCAL_MACHINE;
66 case "HKEY_USERS":
67 return HKEY_USERS;
68 case "HKEY_CURRENT_CONFIG":
69 return HKEY_CURRENT_CONFIG;
70 }
71 
72 return HKEY_CLASSES_ROOT;
73 }
74 
75 public static string Get64BitRegistryKey(string parentKeyName, string subKeyName, string keyName)
76 {
77 int KEY_QUERY_VALUE = (0x0001);
78 int KEY_WOW64_64KEY = (0x0100);
79 int KEY_ALL_WOW64 = (KEY_QUERY_VALUE | KEY_WOW64_64KEY);
80 
81 try
82 {
83 //將Windows登錄檔主鍵名轉化成為不帶正負號的整形控制代碼(與平臺是32或者64位有關)
84 UIntPtr hKey = TransferKeyName(parentKeyName);
85 
86 //宣告將要獲取Key值的控制代碼
87 IntPtr pHKey = IntPtr.Zero;
88 
89 //記錄讀取到的Key值
90 StringBuilder result = new StringBuilder("".PadLeft(1024));
91 uint resultSize = 1024;
92 uint lpType = 0;
93 
94 //關閉檔案系統轉向 
95 IntPtr oldWOW64State = new IntPtr();
96 if (Wow64DisableWow64FsRedirection(ref oldWOW64State))
97 {
98 //獲得操作Key值的控制代碼
99 RegOpenKeyEx(hKey, subKeyName, 0, KEY_ALL_WOW64, out pHKey);
100 
101 //關閉登錄檔轉向(禁止特定項的登錄檔反射)
102 RegDisableReflectionKey(pHKey);
103 
104 //獲取訪問的Key值
105 RegQueryValueEx(pHKey, keyName, 0, out lpType, result, ref resultSize);
106 
107 //開啟登錄檔轉向(開啟特定項的登錄檔反射)
108 RegEnableReflectionKey(pHKey);
109 }
110 
111 //開啟檔案系統轉向
112 Wow64RevertWow64FsRedirection(oldWOW64State);
113 
114 //返回Key值
115 return result.ToString().Trim();
116 }
117 catch (Exception ex)
118 {
119 return null;
120 }
121 }
122 
123 #endregion
124 }
125 }

Get64BitRegistryKey函式的三個引數分別代表:主鍵名(如:HKEY_LOCAL_MACHINE等),子鍵名,關鍵名,返回的是金鑰的值(64位系統登錄檔的鍵值),通過上面的方法就完全可以實現用32程式訪問64位系統登錄檔(即:64位程式所訪問的登錄檔位置)。

轉自:https   //blog.csdn.net/By__myself/article/details/73658027在此感謝!!!

轉自:http://www.cnblogs.com/mingmingruyuedlut/archive/2011/01/21/1941225.html在此感謝!!!