web-dev-qa-db-ja.com

32ビットアプリケーションから64ビットレジストリを読み取る

AnyCPU用にコンパイルされたc#ユニットテストプロジェクトがあります。ビルドサーバーは64ビットマシンであり、64ビットSQL Expressインスタンスがインストールされています。

テストプロジェクトは、次のようなコードを使用して、.MDFファイルへのパスを識別します。

    private string GetExpressPath()
    {
        RegistryKey sqlServerKey = Registry.LocalMachine.OpenSubKey( @"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" );
        string sqlExpressKeyName = (string) sqlServerKey.GetValue( "SQLEXPRESS" );
        RegistryKey sqlInstanceSetupKey = sqlServerKey.OpenSubKey( sqlExpressKeyName + @"\Setup" );
        return sqlInstanceSetupKey.GetValue( "SQLDataRoot" ).ToString();
    }

このコードは32ビットワークステーションで正常に機能し、NCoverでコードカバレッジ分析を最近有効にするまでビルドサーバーで正常に機能しました。 NCoverは32ビットCOMコンポーネントを使用するため、テストランナー(Gallio)は32ビットプロセスとして実行されます。

レジストリを確認すると、「インスタンス名」キーはありません

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server

32ビットモードで実行されているアプリケーションがWow6432Nodeの外部のレジストリにアクセスする方法はありますか?

89
David Gardiner

レジストリキーを作成/開くときにKEY_WOW64_64KEYパラメーターを使用する必要があります。ただし、レジストリクラスでは不可能ですが、APIを直接使用する場合にのみ可能です。

これ は、開始に役立つ場合があります。

19
Stefan

コメントするのに十分な担当者がいませんが、OpenRemoteBaseKeyを使用してリモートレジストリを開くときに機能することを指摘する価値があります。 RegistryView.Registry64パラメーターを追加すると、マシンAの32ビットプログラムがマシンBの64ビットレジストリにアクセスできるようになります。そのパラメーターを渡す前に、プログラムはOpenRemoteBaseKeyの後に32ビットを読み取っていて、キーが見つかりませんでしたI後だった。

注:私のテストでは、リモートマシンは実際には私のマシンですが、別のマシンの場合と同じように、OpenRemoteBaseKeyを介してアクセスしました。

5
Sandra

これを試してください(32ビットプロセスから):

> %WINDIR%\sysnative\reg.exe query ...

ここ )が見つかりました。

4
akira

.NET 4を RegistryKey.OpenBaseKey(..., RegistryView.Registry64) で使用できない場合、Windows APIを直接使用する必要があります。

最小限の相互運用性は次のとおりです。

internal enum RegistryFlags
{
    ...
    RegSz = 0x02,
    ...
    SubKeyWow6464Key = 0x00010000,
    ...
}

internal enum RegistryType
{
    RegNone = 0,
    ...
}

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int RegGetValue(
    UIntPtr hkey, string lpSubKey, string lpValue, RegistryFlags dwFlags, 
    out RegistryType pdwType, IntPtr pvData, ref uint pcbData);

次のように使用します。

IntPtr data = IntPtr.Zero;
RegistryType type;
uint len = 0;
RegistryFlags flags = RegistryFlags.RegSz | RegistryFlags.SubKeyWow6464Key;
UIntPtr key = (UIntPtr)((uint)RegistryHive.LocalMachine);

const string subkey= @"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL";
const string value = "SQLEXPRESS";

if (RegGetValue(key, subkey, value, flags, out type, data, ref len) == 0)
{
    data = Marshal.AllocHGlobal((int)len);
    if (RegGetValue(key, subkey, value, flags, out type, data, ref len) == 0)
    {
        string sqlExpressKeyName = Marshal.PtrToStringUni(data);
    }
}
4
Martin Prikryl