32 ビット アプリケーション内から 64 ビットへのアクセスを提供する Windows サブシステムであるWOW64 により、64 ビット レジストリの読み取りが可能です。(同様に、古い NT ベースの Windows バージョンではWOWと呼ばれ、16 ビット アプリケーションをサポートするための 32 ビット Windows 内のエミュレーション レイヤーでした)。
.NET Framework 4.xを使用した 64 ビット Windows でのレジストリ アクセス、および新しい .NET バージョン (.NET Core、.NET 5 および 6 など) に対するネイティブ サポートも引き続き提供されます。次のコードは、 Windows 7、64 ビット 、および Windows 10、64 ビットでテストされています。Windows 11 でも動作するはずです。
あるレジストリ ツリーを別のレジストリ ツリーにマッピングして仮想的に表示することでノードをエミュレートするを使用する代わりに、次の操作"Wow6432Node"
を実行できます。
64 ビットまたは 32 ビットのレジストリにアクセスする必要があるかどうかを決定し、以下で説明するように使用します。後で説明したコード (追加情報セクション) を使用することもできます。このコードは、1 つのクエリで両方のノードからレジストリ キーを取得するユニオン クエリを作成するため、実際のパスを使用してクエリを実行できます。
64 ビット レジストリ
64 ビットのレジストリにアクセスするにはRegistryView.Registry64
、次のように使用できます。
// using Microsoft.Win32
string value64 = string.Empty;
RegistryKey localKey =
RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
RegistryView.Registry64);
localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey != null)
{
value64 = localKey.GetValue("RegisteredOrganization").ToString();
localKey.Close();
}
Console.WriteLine(String.Format("RegisteredOrganization [value64]: {0}",value64));
32 ビット レジストリ
32 ビット レジストリにアクセスする場合は、次のように使用RegistryView.Registry32
します。
// using Microsoft.Win32
string value32 = string.Empty;
RegistryKey localKey32 =
RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
RegistryView.Registry32);
localKey32 = localKey32.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey32 != null)
{
value32 = localKey32.GetValue("RegisteredOrganization").ToString();
localKey32.Close();
}
Console.WriteLine(String.Format("RegisteredOrganization [value32]: {0}",value32));
混乱しないでください。両方のバージョンが最初のパラメーターとして使用されています。2 番目のパラメーター( vs ) で64 ビットと32 ビットMicrosoft.Win32.RegistryHive.LocalMachine
のどちらを使用するかを区別します。RegistryView.Registry64
RegistryView.Registry32
注意してください
64 ビット Windows ではHKEY_LOCAL_MACHINE\Software\Wow6432Node
、64 ビット システムで実行されている 32 ビット アプリケーションで使用される値が含まれます。HKEY_LOCAL_MACHINE\Software
真の 64 ビット アプリケーションのみが値を直接格納します。サブツリーWow6432Node
は 32 ビット アプリケーションに対して完全に透過的であり、32 ビット アプリケーションはHKEY_LOCAL_MACHINE\Software
期待どおりに表示されます (これは一種のリダイレクトです)。古いバージョンの Windows と 32 ビット Windows 7 (および Vista 32 ビット) では、Wow6432Node
明らかにサブツリーは存在しません。
Windows 7 (64 ビット) のバグにより、32 ビット ソース コード バージョンは登録した組織に関係なく常に "Microsoft" を返しますが、64 ビット ソース コード バージョンは正しい組織を返します。
提供した例に戻って、次の方法で 64 ビット ブランチにアクセスします。
RegistryKey localKey =
RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey sqlServerKey = localKey.OpenSubKey(
@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL");
string sqlExpressKeyName = (string) sqlServerKey.GetValue("SQLEXPRESS");
追加情報 - 実際の使用について:
Johny Skovdalがコメントで提案した興味深いアプローチを追加したいと思います。彼のアプローチを使用していくつかの便利な機能を開発するために取り上げました。 64 ビット。SQL インスタンス名はその一例です。その場合、次のようにユニオン クエリを使用できます (C#6 以降)。
// using Microsoft.Win32;
public static IEnumerable<string> GetRegValueNames(RegistryView view, string regPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
return RegistryKey.OpenBaseKey(hive, view)
?.OpenSubKey(regPath)?.GetValueNames();
}
public static IEnumerable<string> GetAllRegValueNames(string RegPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
var reg64 = GetRegValueNames(RegistryView.Registry64, RegPath, hive);
var reg32 = GetRegValueNames(RegistryView.Registry32, RegPath, hive);
var result = (reg64 != null && reg32 != null) ? reg64.Union(reg32) : (reg64 ?? reg32);
return (result ?? new List<string>().AsEnumerable()).OrderBy(x => x);
}
public static object GetRegValue(RegistryView view, string regPath, string ValueName="",
RegistryHive hive = RegistryHive.LocalMachine)
{
return RegistryKey.OpenBaseKey(hive, view)
?.OpenSubKey(regPath)?.GetValue(ValueName);
}
public static object GetRegValue(string RegPath, string ValueName="",
RegistryHive hive = RegistryHive.LocalMachine)
{
return GetRegValue(RegistryView.Registry64, RegPath, ValueName, hive)
?? GetRegValue(RegistryView.Registry32, RegPath, ValueName, hive);
}
public static IEnumerable<string> GetRegKeyNames(RegistryView view, string regPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
return RegistryKey.OpenBaseKey(hive, view)
?.OpenSubKey(regPath)?.GetSubKeyNames();
}
public static IEnumerable<string> GetAllRegKeyNames(string RegPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
var reg64 = GetRegKeyNames(RegistryView.Registry64, RegPath, hive);
var reg32 = GetRegKeyNames(RegistryView.Registry32, RegPath, hive);
var result = (reg64 != null && reg32 != null) ? reg64.Union(reg32) : (reg64 ?? reg32);
return (result ?? new List<string>().AsEnumerable()).OrderBy(x => x);
}
これで、上記の関数を次のように簡単に使用できます。
例 1: SQL インスタンス名を取得する
var sqlRegPath=@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL";
foreach (var valueName in GetAllRegValueNames(sqlRegPath))
{
var value=GetRegValue(sqlRegPath, valueName);
Console.WriteLine($"{valueName}={value}");
}
値の名前と sqlRegPath の値のリストが表示されます。
注:上記の対応する関数でパラメーターを省略した場合、キーの既定値 (コマンドライン ツールREGEDT32.EXE
では として表示されます) にアクセスできます。(Default)
ValueName
レジストリ キー内のサブキーのリストを取得するには、関数GetRegKeyNames
またはを使用しますGetAllRegKeyNames
。このリストを使用して、レジストリ内のさらにキーをトラバースできます。
例 2:インストール済みソフトウェアのアンインストール情報を取得する
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
32 ビットおよび 64 ビットのアンインストール キーをすべて取得します。
SQL サーバーは 32 ビットまたは 64 ビットとしてインストールできるため、関数で必要なnull 処理に注意してください(上記の例 1)。関数はオーバーロードされているため、必要に応じて 32 ビットまたは 64 ビットのパラメーターを渡すことができます。ただし、省略した場合は 64 ビットを読み取ろうとし、失敗した場合 (null 値)、32 ビット値を読み取ります。
ここには 1 つの特殊性があります: は通常ループ コンテキストで使用されるため(上記の例 1 を参照)、ループを単純化するGetAllRegValueNames
のではなく、空の列挙型を返します。それをしなければならない面倒なステートメントチェック - そのため、関数で一度処理されます。null
foreach
if
null
なぜnullを気にするのですか?気にしないと、null 参照例外がコードでスローされた理由を見つけるために、さらに多くの頭痛の種が発生するためです。どこで、なぜ発生したのかを調べるのに多くの時間を費やすことになります。そして、それが本番環境で発生した場合、ログファイルやイベントログの調査に非常に忙しくなります(ログが実装されていることを願っています)...防御的な方法でできる限り、nullの問題を回避することをお勧めします。演算子?.
, ?[
... ]
and??
は非常に役に立ちます (上記のコードを参照してください)。C# の新しい null 許容参照型について説明している素敵な関連記事があります。これを読むことをお勧めします。Elvis 演算子についての記事もあります。
ヒント:無料版のLinqpadを使用して、 Windows ですべての例をテストできます。インストールは必要ありません。を押して、[名前空間のインポート] タブにF4入力することを忘れないでください。Visual Studio では、コードの先頭にMicrosoft.Win32
必要です。using Microsoft.Win32;
ヒント:新しいnull 処理演算子に慣れるには、LinqPad で次のコードを試して (およびデバッグして)ください。
例 3: null 処理演算子のデモ
static string[] test { get { return null;} } // property used to return null
static void Main()
{
test.Dump(); // output: null
// "elvis" operator:
test?.Dump(); // output:
// "elvis" operator for arrays
test?[0].Dump(); // output:
(test?[0]).Dump(); // output: null
// combined with null coalescing operator (brackets required):
(test?[0]??"<null>").Dump(); // output: "<null>"
}
.Net フィドルで試してみてください
興味がある場合は、このツールで他に何ができるかを示すいくつかの例をまとめました。