C#のレジストリによる読み書きとバージョンアップ

本記事は、C#での設定ファイル管理とパラメータのバージョンアップの連載の一部として、レジストリによる設定情報やパラメータの扱いについて記載します。アプリケーションの設定情報を保存し、読み込む方法はいろいろあり、レジストリを利用するのはその中でも一番古い方法の一つであるが、設定ファイルをレジストリだけで構成するアプリケーションはほぼないでしょう。アプリケーションにとって本当に大事な情報を扱う時、どうしても必要だと判断した場合のみ使うとよいでしょう。

レジストリのどこに書き込むべきか

どんな設定情報を管理する方法でも、設定情報をどこに置くかは悩みのところですね。レジストリを利用する場合は、大きく以下の2つに分けることができます。

フィールド 主な使い道
Registry.LocalMachine Windowsのログインユーザに何系なく、全ユーザ共有の領域
Registry.CurrentUser Windowsのログインユーザ毎の領域
 アプリケーションの目的や利用パターンによって異なるとは思いますが、マイクロソフト社はセキュリティ面でRegistry.CurrentUserを勧めているようです(利用制限することになるのであたまり前な話になってしまいますね。)

x86とx64のアプリケーションとOS環境

WindowsのOS(32bit,64bit)とアプリケーションのBuild条件によって実際扱われる場所が変わりますので注意が必要です。

・以下、Registry.CurrentUser.OpenSubKey()利用した場合、固定されるレジストリの場所(パス)です。

Build条件と実行OS環境 レジストリ場所(パス)
Build OS
x86 32bit HKEY_CURRENT_USER\Software
64bit HKEY_CURRENT_USER\Software\Wow6432Node
x64 32bit x64でBuildし、32bitOSで使うことはできません
64bit HKEY_CURRENT_USER\Software
AnyCPU 32bit HKEY_CURRENT_USER\Software
64bit HKEY_CURRENT_USER\Software

管理者の場合は、64bitのOSがはやり始まった時、Win32(x86)のアプリケーションを開発することになり、Wow6432Nodeに保存されることで、苦労したことがあります。(開発の初期にAnyCPUとx86が両方存在した状態でデバッグしていたためでした。開発環境統一は大事ですね)

レジストリの読み書き

レジストリを利用するためのクラス

レジストリに書き込むフィールド(場所)によって、使うクラスが別途用意されています。

フィールド レジストリを利用するためのクラス
Registry.LocalMachine Microsoft.Win32.Registry.LocalMachine
Registry.CurrentUser Microsoft.Win32.Registry.CurrentUser

レジストリ読み書きとデータクラスの結び付け

レジストリは利用するのが特集なケースが多いと思うので、必ずしもINIのように起動時にクラスへ変換する必要がないかもしれませんが、管理者は好みによってレジストリ読み書きクラスを作り、データクラスと結び付けてみました。

  • サンプルで使うデータクラス

  • 呼び出し側

  • レジストリの読み書きを扱うための規定クラス

レジストリを扱うための規定クラスを定義してみました(細かい例外処理などは行っていませんので、ご了承ください)。このクラスをそのまま使うか、少し変更して使うと、レジストリを扱う時には少し楽になると思います。

レジストリを扱うにおいて、注意したいこと

・文字列扱う型(REG_SZ,REG_EXPAND_SZ)の場合、最大1024bytesまでしか扱いません。もし、このサイズを超える場合は、文字列を分割して複数のkeyにするか、他の設定ファイルをなどを用意すると良いです。

・Registry.LocalMachineを扱う時は、管理者権限が必要になります。アプリケーションを使う側が管理者権限を持っているいるユーザになる予定なのか、仕様を確認して注意して扱うと良いです。

実際のクラスを使ってレジストリを使う

基本は、[C#のINIによる設定ファイルとバージョンアップ]の記載と同じく、レジストリを直接扱うのではなく、Wrapperクラスを作成しています。1~2個レベルのクラスメンバーであれば、ここまでやる必要はないでしょう。都合によりレジストリを使うパラメータが多くなった場合は、このようにWrapperクラスを作成して使うとよいでしょう。複数のクラスになる場合は、今回のサンプルのように規定クラスにGet,Set関連関数を移動すると良いです。

パラメータバージョンアップにおけるレジストリ管理による影響

レジストリを使うというのは、INIファイルによって管理するのと同じく、クラス情報をそのままレジストリに保存することはなく、一度、変換を行うことになる。そのため、INIファイルによる設定ファイルの管理と同じく、パラメータバージョンアップの際も、基本は影響を受けません。なので、クラスのメンバー毎に読み込みと書き込みの変換の実装が必要ですが、その分、バージョンアップによってパラメータが増えても素直に実装できるメリットがあるのが特徴です。

まとめ

レジストリによるパラメータ管理は、レジストリだけを使って大規模なアプリケーションを構築することはないでしょう。アプリケーションとして本当に大事な情報やレジストリである必要がある部分だけをレジストリを使って管理すると良いです。たとえば、アプリケーションのインストーラと関わる情報(例えば、ユーザが任意のフォルダを削除しても動作し続けるようにした場合など)や他のモジュールとのインタフェースでどうしても共通の部分はレジストリを使って実装することがありえると思います。