.NET Framework 4.xを使用した64ビットWindowsでのレジストリアクセスのネイティブサポートはまだあります。次のコードは、Windows 7、64ビット 、および Windows 10、64ビットでテストされてい ます。
"Wow6432Node"
1つのレジストリツリーを別のレジストリツリーにマッピングしてノードを仮想的にそこに表示することでノードをエミュレートするを使用する代わりに、次のように実行できます。
64ビットレジストリと32ビットレジストリのどちらにアクセスする必要があるかを決定し、以下の説明に従って使用します。後で説明するコード(追加情報セクション)を使用して、ユニオンクエリを作成し、1つのクエリで両方のノードからレジストリキーを取得することもできます。そのため、実際のパスを使用してクエリを実行できます。
64ビットレジストリ
64ビットレジストリにアクセスするにはRegistryView.Registry64
、次のように使用できます。
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
、次のように使用します。
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));
両方のバージョンを使用している、混同しないでくださいMicrosoft.Win32.RegistryHive.LocalMachine
最初のパラメータとしては、使用するかどうかを区別します64ビットまたは32ビットのことで第二のパラメータ(RegistryView.Registry64
対をRegistryView.Registry32
)。
注意してください
64ビットWindowsでは、HKEY_LOCAL_MACHINE\Software\Wow6432Node
64ビットシステムで実行されている32ビットアプリケーションで使用される値が含まれます。真の64ビットアプリケーションのみが値をHKEY_LOCAL_MACHINE\Software
直接格納します。サブツリー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がコメントで提案した興味深いアプローチを追加したいと思います。コメントを参考にして、彼のアプローチを使用していくつかの便利な機能を開発しました。状況によっては、32ビットか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ビットとしてインストールできるため(上記の例1)、関数で必要なnull処理に注意してください。関数はオーバーロードされているため、必要に応じて32ビットまたは64ビットのパラメーターを渡すことができます。ただし、省略した場合、64ビットの読み取りが試行され、失敗した場合(null値)、32ビットの値が読み取られます。
ここには1つの特別な点があります。これGetAllRegValueNames
は通常ループコンテキストで使用されるため(上記の例1を参照)、ループnull
を単純化foreach
するのではなく、空の列挙型を返します。そのように処理されない場合、ループの前にこれif
をチェックnull
するのが面倒なステートメントをチェックするステートメント-関数内で一度処理されます。
なぜnullを気にするのですか?気にしないと、コード内でnull参照例外がスローされた理由を突き止めるのに多くの頭痛が発生するため、どこで、なぜ発生したかを突き止めるのに多くの時間を費やすことになります。また、本番環境で発生した場合は、ログファイルやイベントログの調査で忙しくなります(ロギングが実装されているといいのですが)...防御的な方法でできるnullの問題を回避することをお勧めします。演算子?.
、?[
...は]
、??
あなたを大いに助けることができます(上記のコードを参照してください)。C#の新しいnull可能参照型について説明しているすばらしい関連記事があります。これは、私が読むことをお勧めします。また、Elvisオペレーターに関するこの記事もお勧めします。
ヒント:Linqpadの無料版を使用して、Windowsですべての例をテストできます。インストールは必要ありません。名前空間インポートタブを押しF4て入力することを忘れないでくださいMicrosoft.Win32
。Visual Studioではusing Microsoft.Win32;
、コードの先頭にが必要です。
ヒント:新しいを理解するには、ヌル取り扱い事業者、 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フィドルでお試しください
あなたが興味を持っているなら、ここに私がまとめたいくつかの例があります。このツールで他に何ができるかを示しています。