トップ回答者
レジストリキーから2つの値を読む方法について

質問
-
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();
回答
-
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);
# 個人的には定数を変数にせずに直接埋め込みます。一旦変数に置くと、今回のように問題個所が曖昧になり、調査の妨げになるからです。
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年10月20日 1:41
- 回答としてマーク lga_im 2017年10月20日 2:10
- 回答としてマークされていない lga_im 2017年10月20日 2:10
- 回答としてマーク lga_im 2017年10月20日 2:10
すべての返信
-
サンプルが悪いだけで、実際の rKeyName1 と rKeyName2 は違うのでしょうか?
同じなのであれば、いちいち Close せず、一気に GetValue すべきだと思います。その行で NullReferenceException が発生しているなら、rKey2 が null、つまり、OpenSubKey に失敗しています。
失敗する理由はなんともわかりませんが…。- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年10月20日 1:41
-
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);
# 個人的には定数を変数にせずに直接埋め込みます。一旦変数に置くと、今回のように問題個所が曖昧になり、調査の妨げになるからです。
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年10月20日 1:41
- 回答としてマーク lga_im 2017年10月20日 2:10
- 回答としてマークされていない lga_im 2017年10月20日 2:10
- 回答としてマーク lga_im 2017年10月20日 2:10