もっと詳しく

自作プログラムを作成していると、画面から入力した値をファイルに保存しておき、次回起動時に復元したくなることが多々ありますよね。

やり方は色々とありますが、今回は多くのアプリで使われている最も標準的な app.config に保存する方法を紹介したいと思います。

あまり他のサイトでは触れられていない、app.configに対するプログラムからの変数追加や削除の仕方や、さらに手軽に使えるようクラス化したサンプルも用意しています。

app.config で設定値を管理したい方は、是非ご一読ください。

app.config の概要

いちおう念のため簡単に説明しておきます。

app.conifig は別名「アプリケーション構成ファイル」とも呼ばれている Microsoft .NET 標準の設定値保存場所です。

app.config は通称で、実際にはアプリケーション名.exe.Config

通常、EXEファイルと同じフォルダに作成されますが、指定の仕方によっては一部ユーザーフォルダに置かれます(後述)。

App.Configには2種類のクラス(Propertiesと Configuration)が用意されており、それぞれ役割とスコープを持っています。

詳細については後ほど説明しますが、App.configに設定値を保存する場合、保存先として3種類のタグが用意されており、それぞれ役割が異なる点は理解しておきましょう。

最初の準備

App.config に書き込むには、System.Configuration の参照が必要となります。

尚、.NET Core 6 以降は参照設定は不要です。

次に、プログラム先頭に下記の1行を追加しておきます。

using System.Configuration;

Configurationを用いたApp.configの参照と保存

EXEファイルと同じフォルダにある app.config に、キー(変数名)と値を対にして保存、読み出しが可能です。

尚、値の型は文字列だけであるため、数値や日付などを保存する場合は、読み出し時に Parse メソッドなどでの変換が必要となります。

ちなみに、他のサイトでは殆ど触れられていませんが、アプリから動的に設定値を追加したり削除したりすることも可能です。

App.config を編集して設定値の追加/削除を行う

Visual Studio のソリューションにある App.config に対して直接記述します。

下記は Name いうキー(変数名)に”山田太郎”という初期値を設定し、Ageというキーに”29″という年齢を設定しています。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="Name" value="山田太郎" />
        <add key="Age" value="29" />
    </appSettings>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
  
</configuration>

プログラムから設定値を参照する

プログラムから値を参照するのは簡単で、次の1行だけでOKです。 

  ConfigurationManager.AppSettings[”キー名”]  

インスタンスの生成も不要です。

下記は、XAML 上で定義した2つのテキストボックス(uxName,uxAge)に、それぞれ “Name” と “Age” のキーで参照した値をセットするサンプルです。

uxName.Text = ConfigurationManager.AppSettings["Name"];
uxAge.Text = ConfigurationManager.AppSettings["Age"];

プログラムから設定値を更新する

設定値を更新する場合、ConfigurationManager から Configuration のインスタンスを取得し、これを通して値を設定します。

下記は、2つのテキストボックスの内容で設定値を更新するサンプルです。

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["Name"].Value = uxName.Text;
config.AppSettings.Settings["Age"].Value = uxAge.Text;

もし存在しないキーに対して値を代入すると例外が発生しますので、ご注意ください。

そもそも、App.config はアプリケーションの設定値を管理する用途で使われるため、存在しないキーを指定するケースは単なるプログラミングのミスによるものだと思います。

しかし、もし万が一画面から入力された設定値を、新たなキーをつかって追加するような場合は、

 AppSettings.Settings.AllKeys

というキーを全て取得するプロパティが用意されているので、これが使えます。

例えば、”Address”というキーが存在するかをチェックする場合は、次のように記述できます。

if(config.AppSettings.Settings.AllKeys.Contains("Address"))){ }

設定値を App.config に保存する

config.AppSettings.Settings[“キー名”].Value に値を代入したからと言って、その時点で App.config に保存される訳ではありません。

Save() メソッドを呼ぶことで、初めて App.config が更新されます。

configuration.Save();

さて、Save() メソッドを呼んだ時点で App.config が更新されるということは、その直後に ConfigurationManager.AppSettings[“キー名”] で参照したら、更新後の値が取得できると思いませんか?

答えはノーです。

ConfigurationManager から取得した Configration への変更は、ConfigurationManager には反映されません。

あくまでもプログラム起動時に設定を読み込んで、終了時に App.config に書き込むという使い方が想定されています。

アプリから動的に設定値の追加/削除を行う

アプリから動的に設定値を登録するには Add() メソッドが、削除するにはRemove()メソッドが用意されています。

Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

//キーの追加
configuration.AppSettings.Settings.Add("Address", "大阪府");
//キーの削除
configuration.AppSettings.Settings.Remove("Address");

Propertiesを用いたApp.configの参照と保存

Properties を使ってApp.config を保存する場合、あらかじめプロジェクト⇒プロパティ⇒設定 で登録画面を呼び出し、ここから設定します。

App.configを直接編集してもよいのですが、単純にキーと値だけを登録するだけでは正しく動作しません。

たくさん登録したい場合は、一旦1~2個だけ画面から登録しておき、それを参考にApp.configを編集する方法が無難です。

さて、ConfigurationManager との違いは、以下の2点です。

  • スコープ(アプリケーション/ユーザー)が設定できる
  • データ型が指定できる

スコープについて

スコープは2つあって、1つはアプリケーション内で共通の設定値を管理する「アプリケーションスコープ」と、もう1つはユーザー毎の設定値を管理する「ユーザースコープ」です。

アプリケーションスコープとユーザースコープは保存される場所が異なっており、ユーザースコープはC:\Users\ユーザー名\AppData\Local\・・・・ という具合に隠しフォルダの深い階層に配置されます。

スコープ毎の特徴と用途を下記の表にまとめてみました。

スコープ 特徴/用途
アプリケーション 参照のみ。
アプリケーションに共通した初期値を登録する。
EXEファイルと同じフォルダの App.config が使用される。
ユーザー 参照/更新が可能。
ユーザー毎に異なる可能性がある設定値を管理する。
ユーザーのホームディレクト内の隠しフォルダ下に保存される。

プログラムから設定値を参照する

添え字にキー名を指定する方法の他、通常のプロパティのようにドットに続けてキーを指定することも可能です。

  Properties.Settings.Default[“キー名”]

  Properties.Settings.Default.キー名

添え字にキー名を指定する方法では、戻り値がオブジェクト型になるので、キャストが必要となります。

一方、ドットに続けてキー名を指定する場合は、設定した型で値を受け取れます。

例えば、app_value というキー名に double 型を指定した場合、次の2通りの書き方ができます。

//添え字を使う方法(オブジェクト型で返されるので、キャストが必要)
double val = (double)Properties.Settings.Default["app_value"]

//ドットの後にキーを指定する方法(それぞれの型で返されるので、キャストが不要)
double val = Properties.Settings.Default.app_value

プログラムから設定値を更新する

参照の時とは逆に、値を代入するだけです。

ConfigurationManager から Configurationを取得するような事も必要ありません。

//添え字を使う方法
Properties.Settings.Default["app_value"] = "abcde";

//ドットの後にキーを指定する方法
 Properties.Settings.Default.app_value = "abcde";

設定値を App.config に保存する

Save() メソッドが用意されていますので、最後にこれを呼び出します。

Properties.Settings.Default.Save();

サンプルプログラム

ConfigurationManager を使った App.config の参照と保存が手軽になるようにクラス化してみました。

使い方

Button1 クリックのイベントハンドラには、指定したキー名でApp.config から設定値を取得し、テキストボックスに代入する方法を記載しています。

Button2クリックのイベントハンドラには、テキストボックスの値を App.config に保存する方法を記載しています。

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        //インスタンスの生成
        AppSetting _setting = new AppSetting();

        public MainWindow()
        {
            InitializeComponent();
        }

        //設定値の取得
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            uxName.Text = _setting["Name"].ToString();
            uxAge.Text = _setting["Age"].ToString();
        }

        //設定値の保存
        private void Button2_Click(object sender, RoutedEventArgs e)
        {
            _setting["Name"] = uxName.Text;
            _setting["Age"] = uxAge.Text;
            _setting.Save();
        }
    }
}

ソースコード

ソースコードは以下の通りです。

コンストラクタで App.config から全てのキーと値を取得し、辞書に登録しています。

新しくキーを追加したり削除する場合は、辞書とApp.config の両方に同時に反映しています。

また、存在しないキーを指定した場合、新たにキーを作るようにもなっています。

public class AppSetting
{
    private Configuration _configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    private Dictionary<string, string> Settings { get; set; } = new Dictionary<string, string>();
    public string this[string name] { get { return Get(name); } set { Set(name,value); } }
    public AppSetting()
    {
        //App.configに存在するキーと値を辞書に読み込む
        foreach (var key in _configuration.AppSettings.Settings.AllKeys)
        {
            Settings.Add(key, _configuration.AppSettings.Settings[key].Value);
        }
    }

    /// <summary>
    /// 指定したキー名で値を参照
    /// キーが存在しなければ、値が空の新しいキーを登録し、その値を返す
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public string Get(string key)
    {
        if (!Settings.ContainsKey(key))
        {
            Set(key, "");
        }
        return Settings[key];
    }

    /// <summary>
    /// 指定したキーで値を登録
    /// キーが存在しなければ、新しいキーを登録する
    /// </summary>
    /// <param name="key"></param>
    /// <param name="value"></param>
    public void Set(string key,string value)
    {
        if (! Settings.ContainsKey(key))
        {
            Settings.Add(key, value);
            _configuration.AppSettings.Settings.Add(key, value);
        }
        Settings[key] = value;
        _configuration.AppSettings.Settings[key].Value = value;
    }

    /// <summary>
    /// 指定したキーを削除する
    /// </summary>
    /// <param name="key"></param>
    public void Remove(string key)
    {
        Settings.Remove(key);
        _configuration.AppSettings.Settings.Remove(key);
    }

    /// <summary>
    /// App.config に保存する
    /// </summary>
    public void Save()
    {
        _configuration.Save();
    }
}

まとめ

今回は アプリからApp.config に設定値を保存したり、読み出したりする方法について紹介致しました。

App.configに対して読み書きすると言っても、ConfigurationManager を使う方法と、Properties を使う方法の2通りがあり、Propertiesを使う場合はアプリケーションスコープとユーザースコープの2通りの指定が可能でしたね。

更にConfigurationManager をもっと簡単に使うためにクラス化したサンプルソースについても、使い方とソースコードを紹介しました。

設定値は自力でファイルに保存することも可能ですが、ちょっとしたものだと App.config を使う方が断然便利です。

参照設定をするという一手間だけで使えるようになるので、是非皆さんもご活用下さい。