前回の記事で「64 ビット プラットフォームでのレジストリの読み取りと書き込みにおける 32 ビット プログラムと 64 ビット プログラムの違い」について説明しました。次に、前回の記事で残った質問に答えます。ビット プログラムは 64 ビット システム レジストリ (つまり、64 ビット プログラムがアクセスするレジストリの場所) にどのようにアクセスしますか。
私たちはすでに知っています:
①: ネイティブ モード 64 ビット プログラムはネイティブ モードで実行され、次のレジストリ サブキーに格納されているキーと値にアクセスします: HKEY_LOCAL_MACHINESoftware
②: 32 ビットプログラムは WOW64 モードで実行され、アクセス キーと値は次のレジストリ サブキーに保存されます: HKEY_LOCAL_MACHINESoftwareWOW6432nod
したがって、64 ビットのレジストリ情報にアクセスする 32 ビット プログラムを実装するには、次の概念も知っておく必要があります。 1: ファイル システムのリダイレクト。 2: レジストリのリダイレクト (方向)。 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 ファイル (x86) の下にあります。 32 ビット プログラムを使用して %windir%system32 にアクセスすると、ハード コーディングを使用するか他の方法を使用するかに関係なく、システムは自動的に %windir%syswow64 にリダイレクトします。このリダイレクトは、すべての 32 ビット アプリケーションでデフォルトでオンになります。しかし、この種のリダイレクトは必ずしも必要というわけではありません。次に、C# で関連する API を呼び出して、この種のステアリングを閉じたり開いたりすることができます。よく使用される関数は 3 つあります:
Wow64DisableWow64FsRedirection (システム リダイレクトをオフにする)、
Wow64RevertWow64FsRedirection (システム リダイレクトをオンにする)、
4EnableWow64FsRedirection (システムのリダイレクトを有効にします)。
wow6444enablewow64fsredirectionはネストされたモードで使用すると信頼できないため、上記のwow64revertwow64fsredirectionは通常、ファイルシステムのリダイレクトを開くために使用されます。したがって、ネストした形式で使用すると、通常は信頼性が低くなります。 C# では、DllImport を使用してこれら 2 つの関数を直接呼び出すことができます。
②:レジストリリダイレクト(リダイレクト)
32ビットと64ビットのCOM登録とプログラムの共存状態をサポートするために、WOW64サブシステムは32ビットプログラムで使用されるレジストリの別のビューを提供します。 WOW64 サブシステムのレジストリを使用する
ビットレベルのレジストリ呼び出しのインターセプトをリダイレクトします。レジストリ リダイレクトにより、レジストリ呼び出しがレジストリ内の正しいブランチに確実に送信されるようになります。
新しいプログラムをインストールするとき、または Windows x64 バージョンのコンピューターでプログラムを実行するとき、HKEY_LOCAL_MACHINESoftware レジストリ サブキーにアクセスするために 64 ビット プログラムによって行われるレジストリ呼び出し
リダイレクトされません。 WOW64 は、32 ビット プログラムによって HKEY_LOCAL_MACHINESoftware に対して行われたレジストリ呼び出しをインターセプトし、それらを
HKEY_LOCAL_MACHINESoftwareWOW6432node サブキーにリダイレクトします。 WOW64 は 32 ビット プログラム呼び出しのみをリダイレクトすることで、プログラムが常に対応するレジストリ サブキーに書き込むようにします。
レジストリのリダイレクトにはプログラムコードの変更は必要なく、このプロセスはユーザーに対して透過的です。
③:レジストリリフレクション
リフレクションにより、同じレジストリの2つの物理コピーの存在が可能になり、ネイティブとWOW64の同時操作をサポートします
64ビットレジストリを開きます セクションはいつでも利用できますレジストリ リフレクションは、32 ビットに対応するリアルタイムの方法を提供します。
これらを簡単に理解した後、具体的な 実装手順について説明します。
664ビット(ファイルシステム)操作リダイレクトをオフにしますcorpution操作キー値にハンドルを取得
in in in in on in 特定項目のレジストリ反映 ——特定項目のレジストリ反映 ) 特定項目のレジストリ反映 )
名前空間の紹介: 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 関数の 3 つのパラメーターは次を表します: 主キー名 (HKEY_LOCAL_MACHINE など)、サブキー名、キー名はキーの値 (64 ビットのキーの値) を返します。上記の方法により、32 ビット プログラムを使用して 64 ビット システム レジストリ (つまり、64 ビット プログラムがアクセスするレジストリの場所) にアクセスすることが完全に可能になります。
以上が64 ビット レジストリにアクセスするための C# 32 ビット プログラムのサンプル コードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。