連載
» 2005年02月11日 05時00分 UPDATE

.NET TIPS:アプリケーション設定情報はどこに保存すべきか?

[一色政彦,デジタルアドバンテージ]
.NET TIPS
Insider.NET


「.NET TIPS」のインデックス

連載目次

 .NETアプリケーションでその設定情報を永続化(=保存)する際の主要な格納方法(以降、永続化方法)としては、以下の表にある「レジストリ」「XMLファイル」「INIファイル」「まったく独自のファイル・フォーマット」という4種類が利用できる。

永続化方法 利用基準 特徴・利用方法
XMLファイル .NET標準。基本的にこれを利用する 単なるテキスト・ファイルなので手軽にユーザーが参照・編集することが可能。ちなみに.NETでは「構成ファイル(.configファイル)」と呼ばれるXMLファイルがあらかじめ準備されている
【利用方法】XMLファイルへの入出力方法は、後日公開予定のTIPSで紹介する
レジストリ 設定情報をできるかぎりユーザーから隠ぺいしたい場合に利用する。ただしそのデータのサイズが大きい(=64Kbytesを超えるような)場合には利用すべきではない ユーザーが手軽に参照・編集することはできない。レジストリ・エディタを使えば可能
【利用方法】「TIPS:レジストリの値を取得するには?」「TIPS:レジストリの値のデータ型を判別するには?」「TIPS:レジストリの値を設定するには?」などを参照
INIファイル 既存の従来型アプリケーションなど、利用している設定情報を.NETへ移行させる場合に利用する 単なるテキスト・ファイルなので手軽にユーザーが参照・編集することが可能
【利用方法】「TIPS:INIファイルを読み書きするには?」を参照
独自ファイル形式 暗号化するなどしてユーザーから完全に隠ぺいしたいときなどに利用する 基本的にユーザーはその内容を参照・変更することはできない
【利用方法】独自形式データのファイルへの入出力方法は後日公開予定のTIPSで紹介する
.NETアプリケーションにおける主なアプリケーション設定情報の永続化方法

 これらの永続化方法は、その保存場所によりファイル(XMLファイル、INIファイル、独自ファイル形式の場合)とレジストリの2つに分類できる。それでは、具体的にどのパス(ディレクトリあるいはレジストリ・キー)に設定情報を作成・保存すればよいのだろうか。

 本稿では、その設定情報格納先のパスを決定する方法を紹介する。

.NET機能を利用した設定情報格納先パスの決定

 実は.NETでは、このようなパス決定機能が基本機能として提供されている。具体的には、次の表にあるApplicationクラス(System.Windows.Forms名前空間)のプロパティによりパスを決めることができる。

プロパティ 種別/用途 得られるパス
Application.CommonAppDataPath ファイル/
ユーザー共通の設定情報(ローミングしない)
<ベース・パス(CommonApplicationData。例:C:\Documents and Settings\All Users\Application Data)>\<CompanyName>\<ProductName>\<ProductVersion>
Application.UserAppDataPath ファイル/
ユーザー個別の設定情報(ローミングする)
<ベース・パス(ApplicationData。例:C:\Documents and Settings\masa-i\Application Data)>\<CompanyName>\<ProductName>\<ProductVersion>
Application.LocalUserAppDataPath ファイル/
ユーザー個別の設定情報(ローミングしない)
<ベース・パス(LocalApplicationData。例:C:\Documents and Settings\masa-i\Local Settings\Application Data)>\<CompanyName>\<ProductName>\<ProductVersion>
Application.CommonAppDataRegistry レジストリ
/ユーザー共通の設定情報
HKEY_LOCAL_MACHINE\SOFTWARE\<CompanyName>\<ProductName>\<ProductVersion>
Application.UserAppDataRegistry レジストリ
/ユーザー個別の設定情報
HKEY_CURRENT_USER\Software\<CompanyName>\<ProductName>\<ProductVersion>
.NETが提供するパス決定機能
表中の「ローミング」とは、ネットワーク上の複数のコンピュータ間での設定情報の移動のことである(これは「ユーザー・プロファイルのローミング」と呼ばれるWindows機能の1つだ)。ファイルの場合には「ユーザー個別の設定情報(ローミングする)」と「ユーザー個別の設定情報(ローミングしない)」という2種類の用途が提供されている。これらの使い分けの基準としては、その設定情報が「ローカル環境に依存せず、コンピュータ間を移動(=ローミング)してもよい場合」にはApplication.UserAppDataPathプロパティを使い(これにより、ユーザーがコンピュータ間を移動すると、その設定情報も一緒にローミングされる)、その設定情報が「ローカル環境に依存するため、コンピュータ間を移動させたくない場合(例えばモニタ画面などのハードウェアに関する情報の場合)」にはApplication.LocalUserAppDataPathプロパティを使えばよい。

表中のすべてのプロパティはApplicationクラスに定義された読み取り専用の静的プロパティである。これらのプロパティでは、ファイル用のものは文字列としてパスを取得できるが、レジストリ用のものはRegistryKeyクラス(Microsoft.Win32名前空間)のオブジェクトとして取得される。レジストリのパス(=レジストリ・キー)を文字列で取得したい場合には、RegistryKeyオブジェクトのNameプロパティの値を使えばよい。

表中の<ベース・パス>はOS環境によってその値が異なってくるので注意が必要だ。この<ベース・パス>内に( )で記述している「CommonApplicationData」「ApplicationData」「LocalApplicationData」という値は、Environment.SpecialFolder列挙体(System名前空間)の値を示している。これらの値をEnvironmentクラス(System名前空間)のGetFolderPathメソッドのパラメータに引き渡すことで、そのOS環境ごとのベース・パスが取得できる。その具体的なサンプル・コードは、「TIPS:Windowsのシステム・フォルダのパスを取得するには?」を参照してほしい。なお上記のベース・パスの例ではユーザー名が「masa-i」の場合を想定している。

また、表中の<CompanyName>、<ProductName>、<ProductVersion>は、それぞれApplication.CompanyNameプロパティ(会社名)、Application.ProductNameプロパティ(製品名)、Application.ProductVersionプロパティ(製品バージョン)により得られる値である。これらのプロパティ値は、アプリケーションの属性設定(AssemblyCompany属性、AssemblyProduct属性、AssemblyVersion属性)によりプログラム・コードから指定されたものだ。具体的な指定方法は、「TIPS:アセンブリにバージョン情報を設定するには?」を参照してほしい。なお、AssemblyCompany属性やAssemblyProduct属性を指定しなかった場合には、アプリケーションのスタートアップ・オブジェクト(つまりmainメソッドを含むクラス)の「名前空間」の名前が代用される。またAssemblyVersion属性を省略すると、「0.0.0.0」というバージョン番号になる。

 .NETアプリケーションでは基本的に、上記表の「種別/用途」を基準に使うべきプロパティを選択して、そのプロパティから設定情報の格納先パスを取得すればよい。

 しかし場合によっては、これらのプロパティにより得られたパスが問題となることがある。というのも、上記表を確認すれば分かるが、ここで得られたパスには製品バージョン番号(<ProductVersion>)が含まれているため、アプリケーションのバージョンを更新するたびにそのパスが変更されてしまうのだ。よって、もしアプリケーションのバージョンに関係なく同じ設定情報を使用したい場合には上記のプロパティは使えないことになる。

 この問題を回避するには、バージョンに影響されないパス(つまり、<ProductVersion>を含めないパス)を独自に生成するしかないだろう(ただし.NETの上記のプロパティにより提供されるパスは、Windows XPなどが推奨するパス形式に準拠した正当なものである。ここで問題回避のために作成する独自のパスはその準拠からは逸脱しているということになる)。

独自の設定情報格納先パスの決定

 本稿では、バージョン情報を含まない設定情報格納先のパスを取得するためのサンプル・クラスを実装してみた。

using System;
using System.IO;
using System.Windows.Forms;
using Microsoft.Win32;

public class MyApplication
{
  public static string UserAppDataPath
  {
    get
    {
      return GetFileSystemPath(
        Environment.SpecialFolder.ApplicationData);
    }
  }

  public static string CommonAppDataPath
  {
    get
    {
      return GetFileSystemPath(
        Environment.SpecialFolder.CommonApplicationData);
    }
  }

  public static string LocalUserAppDataPath
  {
    get
    {
      return GetFileSystemPath(
        Environment.SpecialFolder.LocalApplicationData);
    }
  }

  public static RegistryKey CommonAppDataRegistry
  {
    get
    {
      return GetRegistryPath(Registry.LocalMachine);
    }
  }

  public static RegistryKey UserAppDataRegistry
  {
    get
    {
      return GetRegistryPath(Registry.CurrentUser);
    }
  }

  private static string GetFileSystemPath(Environment.SpecialFolder folder)
  {
    // パスを取得
    string path = String.Format(@"{0}\{1}\{2}",
      Environment.GetFolderPath(folder),  // ベース・パス
      Application.CompanyName,            // 会社名
      Application.ProductName);           // 製品名

    // パスのフォルダを作成
    lock (typeof(Application))
    {
      if (!Directory.Exists(path))
      {
        Directory.CreateDirectory(path);
      }
    }
    return path;
  }

  private static RegistryKey GetRegistryPath(RegistryKey key)
  {
    // パスを取得
    string basePath;
    if (key == Registry.LocalMachine)
      basePath = "SOFTWARE";
    else
      basePath = "Software";
    string path = String.Format(@"{0}\{1}\{2}",
      basePath,                           // ベース・パス
      Application.CompanyName,            // 会社名
      Application.ProductName);           // 製品名

    // パスのレジストリ・キーの取得(および作成)
    return key.CreateSubKey(path);
  }
}


 上記サンプル・クラスで実装したプロパティの利用例は次のとおりだ(C#の場合)。

string path1 = MyApplication.CommonAppDataPath;
string path2 = MyApplication.UserAppDataPath;
string path3 = MyApplication.LocalUserAppDataPath;
string path4 = MyApplication.CommonAppDataRegistry.Name;
string path5 = MyApplication.UserAppDataRegistry.Name;


 なお、.NET提供のプロパティ、本稿独自作成のプロパティのどちらも、パスを取得する際に自動的にレジストリ・キーやフォルダを作成するので注意してほしい。また、これらのプロパティで得られるパスには、Application.CompanyNameプロパティ(会社名)、Application.ProductNameプロパティ(製品名)、Application.ProductVersionプロパティ(製品バージョン)の値が使われているので(その設定方法については前述のTIPSを参照されたい)、その設定値にパスでは利用できない文字(例えば「/」)が含まれていたりすると、それがアプリケーション・エラーの原因となってしまう可能性がある。注意してほしい。

カテゴリ:クラス・ライブラリ 処理対象:ディレクトリ&ファイル
使用ライブラリ:Applicationクラス(System.Windows.Forms名前空間)
使用ライブラリ:RegistryKeyオブジェクト(Microsoft.Win32名前空間)
使用ライブラリ:Environment.SpecialFolder列挙体(System名前空間)
使用ライブラリ:AssemblyCompany属性(System.Reflection名前空間)
使用ライブラリ:AssemblyProduct属性(System.Reflection名前空間)
使用ライブラリ:AssemblyVersion属性(System.Reflection名前空間)
関連TIPS:Windowsのシステム・フォルダのパスを取得するには?
関連TIPS:アセンブリにバージョン情報を設定するには?
関連TIPS:レジストリの値を取得するには?
関連TIPS:レジストリの値のデータ型を判別するには?
関連TIPS:レジストリの値を設定するには?
関連TIPS:INIファイルを読み書きするには?


「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。