DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

Visual Studioでアプリケーションの設定を保存する

Visual Studio 2005からは、アプリケーションの設定を保存、復元するための機能が追加されました。ここではこの機能の基本的な事柄を紹介します。

なお、Visual Studioを使わずにここで紹介していることとほぼ同じことを行いたい場合は、「ApplicationSettingsBaseクラスを使って設定を保存する」をご覧ください(ただしそちらの記事をご覧になる前に、まずはここの記事に一度目を通して、この機能の概要を知っておいてください)。

さらに、.NET Frameworkのバージョンに依存しない方法については、「アプリケーションの設定を保存する」をご覧ください。

補足:TextBoxのTextやフォームのLocationなど、コントロールのプロパティの値を保存、復元する方法は、「外部ファイルにコントロールのプロパティを格納する」で説明しています。

設定を作成する

まずは、設定を作成します。

プロジェクトのプロパティを表示し(ソリューションエクスプローラでプロジェクトを右クリックして、コンテキストメニューで「プロパティ」を選択するなどで表示できます)、「設定」タブを選択します。

下図のようなグリッドが表示されますので、ここで新しい設定を追加します。ここでは、String型の"Text"を追加するために、「名前」に「Text」、「型」に「String」、「スコープ」に「ユーザー」(スコープについて詳しくは後述)、「値」に「こんにちは。」(これが既定値となる)と入力します。さらに下図のように、Integer型の"Number"も追加し、こちらのスコープは「アプリケーション」にします。

アプリケーションの設定ページ

初めて設定が作成された時にアプリケーション構成ファイル(app.config)が無ければ、新しく作成され、プロジェクトに追加されます。すでにある場合も、新たな要素が追加されます。例えば、次のような記述が追加されます。

VB.NETの場合

C#の場合

設定の値の取得と変更

VB.NETでは、設定プロパティの値の取得と変更は、My.Settingsプロパティ(または、My.MySettings.Defaultプロパティ)で行います。C#では、(プロジェクト名).Properties.SettingsクラスのDefaultプロパティです。設定名と同じ名前のプロパティが作成されていますので、これにアクセスするだけです。ただし、値を設定できるのはユーザースコープの設定だけで、アプリケーションスコープではできません。

先に作成した"Text"の設定の値を取得、変更するには、次のようにします。

VB.NET
コードを隠すコードを選択
'設定Textの値を取得
Console.WriteLine(My.Settings.Text)
'または、次のようにもできる
Console.WriteLine(My.Settings("Text"))

'設定Textの値を変更
My.Settings.Text = "こんばんは。"
'または、次のようにもできる
My.Settings("Text") = "こんばんは。"
C#
コードを隠すコードを選択
//プロジェクト名と同じ名前の名前空間内に記述されているものとする

//設定Textの値を取得
Console.WriteLine(Properties.Settings.Default.Text);
//または次のようにもできる
Console.WriteLine(Properties.Settings.Default["Text"]);

//設定Textの値を変更
Properties.Settings.Default.Text = "こんばんは。";
//または次のようにもできる
Properties.Settings.Default["Text"] = "こんばんは。";

設定の保存と読み込み

上記のように値を変更しただけでは、保存はされません。設定を保存するには、Saveメソッドを呼び出します。

ただしVB.NETでは、通常、アプリケーション終了時に自動的に保存されますので、特に気にする必要はありません。

補足:アプリケーション終了時に設定が自動的に保存されるのは、My.Application.SaveMySettingsOnExitプロパティがTrueの場合です。これを変更するには、プロジェクトのプロパティの「アプリケーション」ページにある、「シャットダウン時に、My.Settingsを保存する」を変更します。

C#では、VB.NETのように自動的に保存されることが無いため、適当なタイミング(フォームのFormClosingイベントなど)でSaveメソッドで保存しなければなりません。

VB.NET
コードを隠すコードを選択
'アプリケーションの設定を保存する
My.Settings.Save()
C#
コードを隠すコードを選択
//アプリケーションの設定を保存する
Properties.Settings.Default.Save();

設定の読み込みは、初めて設定プロパティの値を取得するときに自動的に行われます。

もし、変更された設定の値をすべてSaveメソッドで保存したときの状態に戻したいのであれば、Reloadメソッドを呼び出します。また、保存されている設定を削除して既定値に戻したいのであれば、Resetメソッドを呼び出します。

VB.NET
コードを隠すコードを選択
'アプリケーションの設定を読み込む
My.Settings.Reload()

'既定値に戻す
My.Settings.Reset()
C#
コードを隠すコードを選択
//アプリケーションの設定を読み込む
Properties.Settings.Default.Reload();

//既定値に戻す
Properties.Settings.Default.Reset();

スコープと保存場所

設定には、アプリケーションスコープと、ユーザースコープがあります。

アプリケーションスコープの設定は、アプリケーション毎の設定で、すべてのユーザーで同じ設定が使用されます。また、基本的には読み取り専用で、値の変更や、保存はできません。アプリケーションスコープの設定は、アプリケーション構成ファイル(詳しくは、こちら)に保存されます。

ユーザースコープの設定は、ユーザー毎の設定で、読み取りと書き込みができます。保存される設定は、非ローミングユーザーのアプリケーションデータフォルダに、user.configという名前のXMLファイルとして書き込まれます(注1)。

注1:設定は、「C:\Documents and Settings\UserName\Local Settings\Application Data\CompanyName\(appdomainname)_(eid)_(hash)\1.0.0.0\user.config」のようなパスのファイルに保存されます。なおこのファイル名は、次のようにして取得できます。
VB.NET
コードを隠すコードを選択
Dim config As System.Configuration.Configuration = _
    System.Configuration.ConfigurationManager.OpenExeConfiguration( _
    System.Configuration.ConfigurationUserLevel.PerUserRoamingAndLocal)
Console.WriteLine(config.FilePath)
C#
コードを隠すコードを選択
System.Configuration.Configuration config =
    System.Configuration.ConfigurationManager.OpenExeConfiguration(
    System.Configuration.ConfigurationUserLevel.PerUserRoamingAndLocal);
Console.WriteLine(config.FilePath);

user.configファイルの中身は、例えば、VB.NETでは次のようになります。(C#では、"My.MySettings"の部分が"Properties.Settings"となります。)

ユーザースコープでも、アプリケーション構成ファイルに設定が保存されます。ここに保存された値は、既定値として使用されます。(DefaultSettingValueAttribute属性の値よりも優先されます。)

なお、設定を保存する場所の変更や、レジストリへの保存はできません(注2)。

注2:どのように保存するかは、ApplicationSettingsBase.ProvidersプロパティにあるSettingsProviderオブジェクトで決まりますが、現在はLocalFileSettingsProviderしか用意されていません。この設定プロバイダを自作すれば、別の保存方法でも可能です。設定プロバイダを自作する方法は、「設定プロバイダを自作して、アプリケーション設定がレジストリに保存されるようにする」で説明しています。

設定の値が変更、保存、復元されたことを知る

MySettings(あるいは、Settings)クラスの基本クラスであるApplicationSettingsBaseクラスには、4つのイベントが用意されています。これらのイベントにより、設定の値が変更、保存、復元されたことを知ることができます。これらを表にまとめると、次のようになります。

イベント名 説明(ヘルプより)
PropertyChanged アプリケーション設定プロパティの値が変更された後に発生します。
SettingChanging アプリケーション設定プロパティの値が変更される前に発生します。
SettingsLoaded アプリケーション設定をストレージから取得した後に発生します。
SettingsSaving データ ストアに値が保存される前に発生します。

例えば、設定の値を変更するときに、その値が有効であるか事前に検証したいのであれば、SettingChangingイベントを使います。また、SettingsSavingイベントで保存時に検証することもできます。

以下に、SettingChangingイベントで検証する例を示します。文字列の長さが10より大きい値を設定"Text"に格納できないようにしています。フォームクラスに書かれているものとします。

VB.NET
コードを隠すコードを選択
'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    AddHandler My.Settings.SettingChanging, AddressOf Settings_SettingChanging
End Sub

Private Sub Settings_SettingChanging(ByVal sender As Object, _
        ByVal e As System.Configuration.SettingChangingEventArgs)
    '変更しようとしている設定が"Text"のとき
    If e.SettingName = "Text" Then
        '設定しようとしている値を取得
        Dim str As String = e.NewValue.ToString()
        If str.Length > 10 Then
            '変更をキャンセルする
            e.Cancel = True
        End If
    End If
End Sub
C#
コードを隠すコードを選択
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    Properties.Settings.Default.SettingChanging +=
        new System.Configuration.SettingChangingEventHandler(
            Default_SettingChanging);
}

private void Default_SettingChanging(object sender,
    System.Configuration.SettingChangingEventArgs e)
{
    //変更しようとしている設定が"Text"のとき
    if (e.SettingName == "Text")
    {
        //設定しようとしている値を取得
        string str = e.NewValue.ToString();
        if (str.Length > 10)
        {
            //変更をキャンセルする
            e.Cancel = true;
        }
    }
}

上の例ではフォームのクラス内に記述しましたが、プロジェクトのプロパティの「設定」ページの上に表示される「コードの表示」をクリックして表示される"Settings.vb"(C#では、"Settings.cs")内に記述したほうがよいでしょう。

"Settings.vb"(C#では、"Settings.cs")内に記述する例を示します。今回は少し変えて、SettingsSavingイベントで検証を行います。

VB.NET
コードを隠すコードを選択
Namespace My
    
    'このクラスでは設定クラスでの特定のイベントを処理することができます:
    ' SettingChanging イベントは、設定値が変更される前に発生します。
    ' PropertyChanged イベントは、設定値が変更された後に発生します。
    ' SettingsLoaded イベントは、設定値が読み込まれた後に発生します。
    ' SettingsSaving イベントは、設定値が保存される前に発生します。
    Partial Friend NotInheritable Class MySettings
        Private Sub MySettings_SettingsSaving(ByVal sender As Object, _
                ByVal e As System.ComponentModel.CancelEventArgs) _
                Handles Me.SettingsSaving
            If Me.Text.Length > 10 Then
                '保存をキャンセルする
                e.Cancel = True
            End If
        End Sub
    End Class
End Namespace
C#
コードを隠すコードを選択
namespace CS1.Properties
{
    
    
    // このクラスでは設定クラスでの特定のイベントを処理することができます:
    //  SettingChanging イベントは、設定値が変更される前に発生します。
    //  PropertyChanged イベントは、設定値が変更された後に発生します。
    //  SettingsLoaded イベントは、設定値が読み込まれた後に発生します。
    //  SettingsSaving イベントは、設定値が保存される前に発生します。
    internal sealed partial class Settings
    {
        public Settings()
        {
            // // 設定の保存と変更のイベント ハンドラを追加するには、
            // // 以下の行のコメントを解除します:
            //
            // this.SettingChanging += this.SettingChangingEventHandler;
            
            this.SettingsSaving += this.SettingsSavingEventHandler;
            
        }
        
        private void SettingsSavingEventHandler(object sender,
            System.ComponentModel.CancelEventArgs e)
        {
            // SettingsSaving イベントを処理するコードをここに追加してください。

            if (this.Text.Length > 10)
            {
                //保存をキャンセルする
                e.Cancel = true;
            }
        }
    }
}
補足:上記の例では、イベントハンドラを使用しましたが、代わりにOnSettingsSavingメソッドをオーバーライドする方法も考えられます。

前バージョンの設定を取得する

アプリケーションのバージョン(アセンブリバージョン)が変更されると、前のバージョンで保存された設定の値は無視され、通常の方法では読み込むことができません。前のバージョンのすべての設定を読み込み、新しいバージョンの設定として保存するには、ApplicationSettingsBase.Upgradeメソッドを呼び出します。

また、前のバージョンの特定の設定の値だけを取得するには、GetPreviousVersionメソッドを使用します。

VB.NET
コードを隠すコードを選択
'前のバージョンの設定を読み込み、新しいバージョンの設定とする
My.Settings.Upgrade()

'前のバージョンの設定"Text"の値を取得
Console.WriteLine(My.Settings.GetPreviousVersion("Text"))
C#
コードを隠すコードを選択
//前のバージョンの設定を読み込み、新しいバージョンの設定とする
Properties.Settings.Default.Upgrade();

//前のバージョンの設定"Text"の値を取得
Console.WriteLine(Properties.Settings.Default.GetPreviousVersion("Text"));

これらのメソッドで取得できる設定は直前のバージョンの設定だけで、指定したバージョンの設定を読み込むことはできません。

デザイナの「型」に表示されない型のオブジェクトを設定に追加する

プロジェクトプロパティの「設定」タブページのグリッドには、「型」という列があり、ドロップダウンリストで選択できるようになっています。しかし、自分で作ったクラスなどは表示されません。

それではそのような型のオブジェクトを設定に追加するのは無理かというと、そうではありません。シリアル化できる型であれば、可能です。ただし、Visual Studioのデザイナだけでは、実現できません(注)。MySettings(C#では、Settings)クラスにプロパティを追加するコードを自分で記述することにより、設定として保存できるようになります。

注:「フィードバック: Properties Settings of User Types are Impossible to Add」によると、次のバージョンで可能になるようです。

具体的な例を示しましょう。ここでは、String型を要素に持つジェネリックコレクション(List<string>)を設定として保存できるようにしてみます。

それには、プロジェクトのプロパティの「設定」ページの上に表示される「コードの表示」をクリックして表示される"Settings.vb"(C#では、"Settings.cs")のMySettings(C#では、Settings)クラスに次のようなプロパティを追加します。ここでは設定の名前を、"Lines"としています。

VB.NET
コードを隠すコードを選択
<Global.System.Configuration.UserScopedSettingAttribute()> _
Public Property Lines() As System.Collections.Generic.List(Of String)
    Get
        Return CType(Me("Lines"), System.Collections.Generic.List(Of String))
    End Get
    Set(ByVal value As System.Collections.Generic.List(Of String))
        Me("Lines") = value
    End Set
End Property
C#
コードを隠すコードを選択
[global::System.Configuration.UserScopedSettingAttribute()]
public System.Collections.Generic.List<string> Lines
{
    get
    {
        return ((System.Collections.Generic.List<string>)(this["Lines"]));
    }
    set
    {
        this["Lines"] = value;
    }
}

これで普通に作成された設定と同じように、値の取得、変更、保存、復元等を行えるようになります。

設定ファイルを追加する

プロジェクトのプロパティで表示される設定以外に、別の設定ファイルを作成し、追加することもできます。メニューの「プロジェクト」-「新しい項目の追加」で、新たな設定ファイルを追加できます。

例えば、"ProjectName"というプロジェクトに、"Settings1"という名前の設定ファイルをルートフォルダに作成した場合、設定プロパティ"Message"にアクセスするには、次のようにします。

VB.NET
コードを隠すコードを選択
'設定を変更する
ProjectName.Settings1.Default.Message = "こんにちは。"
C#
コードを隠すコードを選択
//設定を変更する
ProjectName.Settings1.Default.Message = "こんにちは。";
  • 履歴:
  • 2010/10/14 アセンブリバージョンによって設定が変わる説明を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。