none
レジストリキーから2つの値を読む方法について RRS feed

  • 質問

  • visual studio 2017のC#であるレジストリキーから2つの値を読むとき、1つ目は正常に読めますが、
    2つ目を読もうとすると
    Unhandled exception~
    のエラーが発生してしまいます。
    このエラーはリリースモードでビルドしたときに発生し、デバッグモードでは正常に動作してしまいます。
    同じレジストリキーから2つの値を取得する方法についてご教授頂けないでしょうか。

    以下コードの一部と画像はエラーメッセージです。

    string rKeyName1 = @"SOFTWARE\xxx\yyy\drive0";
    string rKeyName2 = @"SOFTWARE\xxx\yyy\drive0";
    string rGetValueName1 = "count1";
    string rGetValueName2 = "show1";

    // レジストリの取得

    RegistryKey rKey1 = Registry.LocalMachine.OpenSubKey(rKeyName1);
    count_int = (int)rKey1.GetValue(rGetValueName1); →この値は取得できます。
    rKey1.Close();

    RegistryKey rKey2 = Registry.LocalMachine.OpenSubKey(rKeyName2);
    dlg_show = (int)rKey2.GetValue(rGetValueName2);  →この行でエラーが発生します。
    rKey2.Close();
    2017年10月19日 9:33

回答

  • Azuleanさんの指摘通りですが、あまり知られていないと思われることなので補足を。

    .NETでは失敗時に例外を投げる仕様で、RegistryKey.OpenSubKey()もその仕様に沿っているように思われがちですが、ドキュメントにもあるようにエラー時は例外を投げ、キーが見つからなかった場合にはnullを返すというややこしい仕様です。実装を見てもERROR_ACCESS_DENIED・ERROR_BAD_IMPERSONATION_LEVEL以外のエラーが発生した場合にはnullを返すコードになっています。

    OpenSubKey()の戻り値はnullチェックを行ってください。もしくはRegistry.GetValue()という別のクラスメソッドが用意されています。こちらであれば質問のコードは次のように書けます。

    count_int = (int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\xxx\yyy\drive0", "count1", -1);
    dlg_show = (int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\xxx\yyy\drive0", "show1", -1);

    # 個人的には定数を変数にせずに直接埋め込みます。一旦変数に置くと、今回のように問題個所が曖昧になり、調査の妨げになるからです。

    2017年10月19日 22:07

すべての返信

  • サンプルが悪いだけで、実際の rKeyName1 と rKeyName2 は違うのでしょうか?
    同じなのであれば、いちいち Close せず、一気に GetValue すべきだと思います。

    その行で NullReferenceException が発生しているなら、rKey2 が null、つまり、OpenSubKey に失敗しています。
    失敗する理由はなんともわかりませんが…。

    2017年10月19日 14:20
    モデレータ
  • Azuleanさんの指摘通りですが、あまり知られていないと思われることなので補足を。

    .NETでは失敗時に例外を投げる仕様で、RegistryKey.OpenSubKey()もその仕様に沿っているように思われがちですが、ドキュメントにもあるようにエラー時は例外を投げ、キーが見つからなかった場合にはnullを返すというややこしい仕様です。実装を見てもERROR_ACCESS_DENIED・ERROR_BAD_IMPERSONATION_LEVEL以外のエラーが発生した場合にはnullを返すコードになっています。

    OpenSubKey()の戻り値はnullチェックを行ってください。もしくはRegistry.GetValue()という別のクラスメソッドが用意されています。こちらであれば質問のコードは次のように書けます。

    count_int = (int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\xxx\yyy\drive0", "count1", -1);
    dlg_show = (int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\xxx\yyy\drive0", "show1", -1);

    # 個人的には定数を変数にせずに直接埋め込みます。一旦変数に置くと、今回のように問題個所が曖昧になり、調査の妨げになるからです。

    2017年10月19日 22:07
  • 質問者様が気にしている「2回続けた事に起因するエラー」なのかの切り分けとして、一度1と2の呼び出しを逆にしてみると分かり易いかもしれませんね。
    2017年10月20日 0:00
  • rKeyName1 と rKeyName2はサンプルどおりの同じキーです。一気にGetValueしてもエラーとなったので、切り分けの為、ひとつずつGetValueしてみました結果ダメだったので、質問させて頂いている次第です。
    2017年10月20日 2:09
  • 佐祐理さん

    Registry.GetValue()を使用したところ、無事レジストリの値を取得することが出来ました。

    ありがとうございます。

    2017年10月20日 2:15