次の方法で共有


C# レジストリの値の取得方法について

質問

2020年2月14日金曜日 23:11

以前、C#言語を用いレジストリ値のデータ取得について質問させていただいた者です。
下記プログラムにてある程度のレジストリ値のデータは取得できるようになったのですが、
今回2つのレジストリ値についてうまく取得することができず、アドバイスをいただきたく投稿させて頂きます。
初心者のため、基礎的な質問だと思いますが、宜しくお願いします。

【使用環境】
 ・Windows10Pro 64Bit Ver1909
 ・Office 365
 ・Visual Studio2019

【現在使用しているプログラム】

string rKeyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Notifications\OptionalFeatures\SMB1Protocol";
string rGetValueName = "Selection";

try
{
RegistryKey rKey = Registry.LocalMachine.OpenSubKey(rKeyName);
int location = (int)rKey.GetValue(rGetValueName);
rKey.Close();
Console.WriteLine(location);
}
catch (NullReferenceException)
{
Console.WriteLine("レジストリ[" ; rKeyName
; "]の[" ; rGetValueName ; "]がありません!");
}

【今回取得したいレジストリ】
●1つ目
 キー: \HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Outlook\Options\Mail
 値 : Receipt response
 想定原因: 値の文字列に半角スペースが入っているため。
       半角スペースの処理がうまくできていないため、該当キーがないと判定される。
●2つ目
 キー:HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Outlook\Profiles\Outlook\0a0d020000000000c000000000000046
 値: 00033d1b 想定原因: 値の形式が『REG_BINARY』のためIncの値をいれようとしてエラーになっている。
       バイナリの処理が理解できていないため、適切な構文を記載できていない。

すべての返信 (5)

2020年2月15日土曜日 0:41

1 スペース含んでいても取れます。
パスを間違えてOpenSubKeyの結果がnullになっていないか、Receipt responseが存在しているか調べてみましょう。

2 バイト配列(byte[])でとれます。

using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Office\16.0\Outlook\Options\Mail"))
{
    if (key == null)
    {
        Console.WriteLine("パスが見つかりません");
    }
    else
    {
        Console.WriteLine(key.Name);

        string name = "Receipt response";
        if (!key.GetValueNames().Any(n => name.Equals(n, StringComparison.OrdinalIgnoreCase)))
        {
            Console.WriteLine(name ; "が存在しません");
        }
        else
        {
            int value = (int)key.GetValue(name);
            Console.WriteLine(name ; " = " ; value);
        }
    }
}

using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Office\16.0\Outlook\Profiles\Outlook\0a0d020000000000c000000000000046"))
{
    Console.WriteLine(key.Name);

    string name = "00033d1b";
    byte[] value = (byte[])key.GetValue(name); //REG_BINARYはバイト配列に
    Console.WriteLine(name ; " = " ; string.Join(" ", value.Select(_ => _.ToString("X02"))));
}

個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)


2020年2月15日土曜日 2:03

string rKeyName = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Notifications\OptionalFeatures\SMB1Protocol";
RegistryKey rKey = Registry.LocalMachine.OpenSubKey(rKeyName);

if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) が true な状態で実行した場合、上記の rKey に null が代入されてしまう可能性があります。IntPtr.Size は 4 と 8 いずれかを返していますか?

// 手元の 64 ビット版 Windows 10 で実験
using (RegistryKey rKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing"))
{
    var keys = rKey.GetSubKeyNames().OrderBy(f => f).ToArray();
    Array.ForEach(keys, Console.WriteLine);
    // 
    // 【Any CPU(32 ビット優先)】【x86】
    // Features on Demand
    // Version
    // 
    // 
    // 【Any CPU】【x64】
    // ApplicabilityEvaluationCache
    // CapabilityIndex
    // ComponentDetect
    // DriverOperations
    // Features on Demand
    // Interface
    // Notifications ←★目的のサブキー★
    // PackageDetect
    // PackageIndex
    // Packages
    // SessionsPending
    // UpdateDetect
    // Version
    // 
    Registry.LocalMachine.Close();
}

想定原因: 値の文字列に半角スペースが入っているため。

手元の環境には、これらが登録されていなかったので確認できないのですが、該当の RegistryKey を開けているのなら、GetValueNames メソッドで値名を列挙できるかを確認し、その値名で GetValueKind メソッドを呼び出せるかどうか確認してみては如何でしょう。

バイナリの処理が理解できていないため、適切な構文を記載できていない。

GetValue メソッドの結果をキャストするだけでは駄目なのでしょうか? GetValue の戻り値を object 型変数に受け取った時、その変数のインスタンスの型は何になっていますか?


2020年2月17日月曜日 17:13

アドバイスいただきありがとうございました。
1.アドバイスいただいた内容をもとに、パスの確認をしたところ、Nullになったのでパスを再度チェックしたところ、
  パスの一部に不要な文字列が含まれていたことが要因だとわかりました。
  調べ方など、教えていただきありがとうございました。

2.Gekkaさんの方法で、バイト配列のデータ取得することができました。ありがとうございます。
  追加の質問となり申し訳ないですが、バイト配列の比較文について教えてください。
  バイト配列値が『00 00 00 00 』ならば【●●に設定されています。】
         『10 00 00 00』ならば【XXに設定されています。】
            『20 00 00 00 』ならば【▼▼に設定されています。】 と表示したいと考えています。  

     単純に下記内容で比較できると考えていたのですが、構文が間違っているため、条件に合致させることができません。

   string ary1 = new string[]{00,00,00,00}
     string ary2 = new string[]{10,00,00,00}
     string ary3 = new string[]{20,00,00,00}

 if (value = ary1){ Console.WriteLine("●●に設定されています。");}
   else if (value = ary2){ Console.WriteLine("××に設定されています。");}
 else if (value = ary3){ Console.WriteLine("▼▼に設定されています。");}
   else{ Console.WriteLine("該当はありません。");}

 当方の環境では、先日ご教授頂いたGekkaさんの方法で『00 00 00 00』が設定されていることはわかっているのですが、
 上記構文では”該当がありません”となってしまいます。


2020年2月17日月曜日 22:45

SequenceEqual を使うか、BitConverter を経由させては如何でしょう


2020年2月19日水曜日 9:21

hornet1119さん、こんにちは。フォーラムオペレーターのクモです。
MSDNフォーラムにご投稿くださいましてありがとうございます。

魔界の仮面弁士さんから参考になる投稿が寄せられたようですね。

そして、「ary_」をbyte[]としてSequenceEqualを使用する必要があります:

Byte[] ary1 = { 0x00, 0, 0, 0 };
            Byte[] ary2 = { 0x10, 0, 0, 0 };
            Byte[] ary3 = { 0x20, 0, 0, 0 };
            Byte[] value = (Byte[])key.GetValue(name);
            if(value.SequenceEqual(ary1))
                Console.WriteLine("●●");
            else if(value.SequenceEqual(ary2))
                Console.WriteLine("××");
            else if (value.SequenceEqual(ary3))
                Console.WriteLine("▼▼");
            else
                Console.WriteLine("None");

またBitConverterも:

 Byte[] value = (Byte[])key.GetValue(name);
            if (value.Length != 4)
                Console.WriteLine("None");
            else
            {
                int value2int = BitConverter.ToInt32(value);
                switch (value2int)
                {
                    case 0:
                        Console.WriteLine("●●");
                        break;
                    case 0x10:
                        Console.WriteLine("××");
                        break;
                    case 0x20:
                        Console.WriteLine("▼▼");
                        break;
                    default:
                        Console.WriteLine("None");
                        break;
                }
            }

どうぞよろしくお願いいたします。 

MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~