• 追加された行はこの色です。
  • 削除された行はこの色です。
#title(33)
#title(.NETプログラミング研究 第33号)

#contents

*33 [#d56991c5]
*.NETプログラミング研究 第33号 [#ab8cb199]

**.NET Tips [#jee6b1bc]

**アプリケーションの設定を保存する [#f26dc7ae]

**コメント [#x40d2a4a]
#column(注意){{
この記事の最新版は「[[アプリケーションの設定を保存する>http://dobon.net/vb/dotnet/programing/storeappsettings.html]]」で公開しています。
}}

アプリケーション終了時に設定を保存しておき、次の起動時に設定を読み込むといった処理を行うためには、設定の情報をファイルに書き込むか、レジストリに書き込むかのどちらかの方法を選ぶことになるでしょう。ここではアプリケーションの設定を保存、復元するための様々な方法を考えます。

***設定はクラスで管理する [#e48c068f]

アプリケーションの設定は、それぞれの設定を別個の変数に入れておくのではなく、すべての設定を一つのクラスにまとめ、そのプロパティとして管理するようにしておくと、何かと便利です。例えば、"Settings"のようなクラスを作成し、アプリのすべての設定がこのクラスのプロパティで取得、設定できるようにします。

ここでは、次のような"Settings"クラスを作成し、このクラスでアプリの全設定を管理するものとします。(ここでは2つのプロパティしかありませんが。)

#code(vbnet){{
Public Class Settings
    Private _text As String
    Private _number As Integer

    Public Property Text() As String
        Get
            Return _text
        End Get
        Set(ByVal Value As String)
            _text = Value
        End Set
    End Property

    Public Property Number() As Integer
        Get
            Return _number
        End Get
        Set(ByVal Value As Integer)
            _number = Value
        End Set
    End Property

    Public Sub New()
        _text = "Text"
        _number = 0
    End Sub
End Class
}}

#code(csharp){{
public class Settings
{
    private string _text;
    private int _number;

    public string Text
    {
        get {return _text;}
        set {_text = value;}
    }
    public int Number
    {
        get {return _number;}
        set {_number = value;}
    }

    public Settings()
    {
        _text = "Text";
        _number = 0;
    }
}
}}

***ファイルに保存する [#f37e89c3]

設定をファイルに保存する方法としては、Windowsでは伝統的にINIファイルが使用されてきました。しかし.NET FrameworkではXMLを扱う機能が充実しており、INIファイルではなく、XMLで保存すべきです。

#column(補足){{
それでもINIファイルを使わなければならない場合もあるでしょう。.NET FrameworkでINIファイルへの保存、復元を行うには、INIファイルをテキストファイルとして扱うか、あるいはWin32 APIのGetPrivateProfileString、WritePrivateProfileString関数などを使うかということになるでしょう。

なお、.NET FrameworkでINIファイルを扱うためのクラスがいくつか公開されていますので、これらを使わせていただくのもよいでしょう。ここでは2つ紹介させていただきます。

-[[The Code Project - IniFile Class using VB.NET>http://www.codeproject.com/vb/net/VbNetClassIniFile.asp]]
-[[The Code Project - An INI file handling class using C#>http://www.codeproject.com/csharp/cs_ini.asp]]
}}

.NET FrameworkでXMLの編集を行うには、通常XmlDocumentクラスを使います。しかし、DOBON.NETで紹介されている「オブジェクトの内容をXMLファイルに保存、復元する」のように、アプリの設定を管理しているクラスのインスタンスをXmlSerializerを使ったシリアル化によりファイルに書き込めば、より簡単に保存することができるでしょう。

-[[オブジェクトの内容をXMLファイルに保存、復元する>http://dobon.net/vb/dotnet/file/xmlserializer.html]]

Settingsオブジェクト"appSettings"をXMLファイルに保存し、復元する簡単なコードを以下に示します。

#code(vbnet){{
Dim appSettings As New Settings

'保存先のファイル名
Dim fileName As String = "C:\settings.config"

'<XMLファイルに書き込む>
'XmlSerializerオブジェクトを作成
'書き込むオブジェクトの型を指定する
Dim serializer1 As New System.Xml.Serialization.XmlSerializer( _
    GetType(Settings))
'ファイルを開く
Dim fs1 As New System.IO.FileStream( _
    fileName, System.IO.FileMode.Create)
'シリアル化し、XMLファイルに保存する
serializer1.Serialize(fs1, appSettings)
'閉じる
fs1.Close()

'<XMLファイルから読み込む>
'XmlSerializerオブジェクトの作成
Dim serializer2 As New System.Xml.Serialization.XmlSerializer( _
    GetType(Settings))
'ファイルを開く
Dim fs2 As New System.IO.FileStream( _
    fileName, System.IO.FileMode.Open)
'XMLファイルから読み込み、逆シリアル化する
appSettings = CType(serializer2.Deserialize(fs2), Settings)
'閉じる
fs2.Close()
}}

#code(csharp){{
Settings appSettings = new Settings();

//保存先のファイル名
string fileName = "C:\\settings.config";

//<XMLファイルに書き込む>
//XmlSerializerオブジェクトを作成
//書き込むオブジェクトの型を指定する
System.Xml.Serialization.XmlSerializer serializer1 =
    new System.Xml.Serialization.XmlSerializer(typeof(Settings));
//ファイルを開く
System.IO.FileStream fs1 =
    new System.IO.FileStream(fileName, System.IO.FileMode.Create);
//シリアル化し、XMLファイルに保存する
serializer1.Serialize(fs1, appSettings);
//閉じる
fs1.Close();

//<XMLファイルから読み込む>
//XmlSerializerオブジェクトの作成
System.Xml.Serialization.XmlSerializer serializer2 =
    new System.Xml.Serialization.XmlSerializer(typeof(Settings));
//ファイルを開く
System.IO.FileStream fs2 =
    new System.IO.FileStream(fileName, System.IO.FileMode.Open);
//XMLファイルから読み込み、逆シリアル化する
appSettings  =
    (Settings) serializer2.Deserialize(fs2);
//閉じる
fs2.Close();
}}

アプリの設定をテキストファイルに保存する欠点として、その内容をユーザーが自由に編集できてしまうという点があります。それを防ぐためには、バイナリファイルに書き込む方法が考えられます。(さらに、バイナリファイルを使ったほうが一般的に読み込み、書込みが速いです。)

オブジェクトの内容をバイナリファイルに保存する簡単な方法として、BinaryFormatterクラスを使う方法が挙げられます。BinaryFormatterを使用してオブジェクトをシリアル化し、FileStreamでファイルに書き込むのです。

まず、SettingsオブジェクトをBinaryFormatterでシリアル化できるようにするために、SettingsクラスにSerializableAttribute属性を付加する必要があります。

#code(vbnet){{
<Serializable()> _
Public Class Settings
    '(省略)
End Class
}}

#code(csharp){{
[Serializable()]
public class Settings
{
    //(省略)
}
}}

Settingsオブジェクト"appSettings"をバイナリファイルに保存し、復元する簡単なコードを以下に示します。

#code(vbnet){{
'Imports System.Runtime.Serialization
'Imports System.Runtime.Serialization.Formatters.Binary
'が先頭に書かれているものとする

Dim appSettings As New Settings

'保存先のファイル名
Dim fileName As String = "C:\settings.config"

'<バイナリファイルに書き込む>
'BinaryFormatterオブジェクトを作成
Dim bf1 As New BinaryFormatter
'ファイルを開く
Dim fs1 As New System.IO.FileStream( _
    fileName, System.IO.FileMode.Create)
'シリアル化し、バイナリファイルに保存する
bf1.Serialize(fs1, appSettings)
'閉じる
fs1.Close()

'<バイナリファイルから読み込む>
'BinaryFormatterオブジェクトの作成
Dim bf2 As New BinaryFormatter
'ファイルを開く
Dim fs2 As New System.IO.FileStream( _
    fileName, System.IO.FileMode.Open)
'バイナリファイルから読み込み、逆シリアル化する
appSettings = CType(bf2.Deserialize(fs2), Settings)
'閉じる
fs2.Close()
}}

#code(csharp){{
//using System.Runtime.Serialization;
//using System.Runtime.Serialization.Formatters.Binary;
//が先頭に書かれているものとする

Settings appSettings = new Settings();

//保存先のファイル名
string fileName = "C:\\settings.config";

//<バイナリファイルに書き込む>
//BinaryFormatterオブジェクトを作成
BinaryFormatter bf1 = new BinaryFormatter();
//ファイルを開く
System.IO.FileStream fs1 =
    new System.IO.FileStream(fileName, System.IO.FileMode.Create);
//シリアル化し、バイナリファイルに保存する
bf1.Serialize(fs1, appSettings);
//閉じる
fs1.Close();

//<バイナリファイルから読み込む>
//BinaryFormatterオブジェクトの作成
BinaryFormatter bf2 = new BinaryFormatter();
//ファイルを開く
System.IO.FileStream fs2 =
    new System.IO.FileStream(fileName, System.IO.FileMode.Open);
//バイナリファイルから読み込み、逆シリアル化する
appSettings  =
    (Settings) bf2.Deserialize(fs2);
//閉じる
fs2.Close();
}}

補足:設定をファイルに保存する方法として、アプリケーション構成ファイルを使用する方法を考えた方もいらっしゃるかもしれません。しかしアプリケーション構成ファイルは読み込み専用ですので、アプリの設定の保存方法としては適切ではありません。

-[[「アプリケーション構成ファイル」を使用して設定を読み込む>http://dobon.net/vb/dotnet/programing/appconfigfile.html]]

***レジストリに保存する [#sa06c18f]

設定を保存する方法として推奨されているのは、レジストリに保存する方法です。ファイルを使用した場合と比べ、レジストリに書き込まれた情報はユーザーによって編集、削除される恐れが少なく、書込みや読み込みが通常はより高速です。ただ、特に簡単なツールのようなアプリの場合、レジストリに設定を書き込むアプリを好ましく思わないユーザーが多いことも事実です。

レジストリにデータを書き込み、読み込む方法を簡単に紹介しておきます。詳しくは、DOBON.NETの「レジストリの操作」をご覧ください。

-[[レジストリの操作>http://dobon.net/vb/dotnet/system/registrykey.html]]

次のコードは、"HKEY_CURRENT_USER\Software\test\subkey"のキー"key"に値"KeyValue"を書き込み、さらに読み込むものです。

#code(vbnet){{
'<レジストリに書き込む>
'サブキーを開く
Dim regkey1 As Microsoft.Win32.RegistryKey = _
    Microsoft.Win32.Registry.CurrentUser.CreateSubKey( _
        "Software\test\subkey")
'文字列を書き込む
regkey1.SetValue("key", "KeyValue")
'閉じる
regkey1.Close()

'<レジストリから読み込む>
'サブキーを読み取り専用で開く
Dim regkey2 As Microsoft.Win32.RegistryKey = _
    Microsoft.Win32.Registry.CurrentUser.OpenSubKey( _
        "Software\test\subkey", False)
'文字列を読み込む
Dim stringValue As String = CType(regkey2.GetValue("key"), String)
'閉じる
regkey2.Close()
}}

#code(csharp){{
//<レジストリに書き込む>
//サブキーを開く
Microsoft.Win32.RegistryKey regkey1 =
    Microsoft.Win32.Registry.CurrentUser.CreateSubKey(
        @"Software\test\subkey");
//文字列を書き込む
regkey1.SetValue("key", "KeyValue");
//閉じる
regkey1.Close();

//<レジストリから読み込む>
//サブキーを読み取り専用で開く
Microsoft.Win32.RegistryKey regkey2 =
    Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
        @"Software\test\subkey", false);
//文字列を読み込む
string stringValue = (string) regkey2.GetValue("key");
//閉じる
regkey2.Close();
}}

***シリアル化してレジストリに保存する [#s501b0df]

設定をファイルに保存する方法では、オブジェクトのシリアル化を利用することにより、より簡単に保存することができました。レジストリへの保存も同じようにできないものでしょうか?

この一つの答えが、Windows Forms FAQの「How do you persist any object in the registry」で紹介されています。

-[[How do you persist any object in the registry>http://www.syncfusion.com/faq/winforms/search/34.asp]]

ここで紹介されている方法は、BinaryFormatterによりオブジェクトをシリアル化し、得られたバイト型配列をレジストリに書き込むというものです。この方法によりSettingsオブジェクト"appSettings"をレジストリに保存し、復元するコードの例を以下に示します。

#code(vbnet){{
'Imports System.IO
'Imports System.Runtime.Serialization
'Imports System.Runtime.Serialization.Formatters.Binary
'が先頭に書かれているものとする

Dim appSettings As New Settings

'<レジストリに書き込む>
Dim ms1 As New MemoryStream
Dim bf1 As New BinaryFormatter
'シリアル化してMemoryStreamに書き込む
bf1.Serialize(ms1, appSettings)
'レジストリへ保存する
Dim regkey1 As Microsoft.Win32.RegistryKey = _
    Microsoft.Win32.Registry.CurrentUser.CreateSubKey( _
        "Software\test\subkey")
regkey1.SetValue("Settings", ms1.ToArray())
'閉じる
ms1.Close()
regkey1.Close()

'<レジストリから読み込む>
Dim bf2 As New BinaryFormatter
'レジストリから読み込む
Dim regkey2 As Microsoft.Win32.RegistryKey = _
    Microsoft.Win32.Registry.CurrentUser.OpenSubKey( _
        "Software\test\subkey", False)
Dim bs As Byte() = CType(regkey2.GetValue("Settings"), Byte())
'逆シリアル化して復元
Dim ms2 As New MemoryStream(bs, False)
appSettings = CType(bf2.Deserialize(ms2), Settings)
'閉じる
ms2.Close()
regkey2.Close()
}}

#code(csharp){{
//using System.IO;
//using System.Runtime.Serialization;
//using System.Runtime.Serialization.Formatters.Binary;
//が先頭に書かれているものとする

Settings appSettings = new Settings();

//<レジストリに書き込む>
MemoryStream ms1 = new MemoryStream();
BinaryFormatter bf1 = new BinaryFormatter();
//シリアル化してMemoryStreamに書き込む
bf1.Serialize(ms1, appSettings);
//レジストリへ保存する
Microsoft.Win32.RegistryKey regkey1 =
    Microsoft.Win32.Registry.CurrentUser.CreateSubKey(
    @"Software\test\subkey");
regkey1.SetValue("Settings", ms1.ToArray());
//閉じる
ms1.Close();
regkey1.Close();

//<レジストリから読み込む>
BinaryFormatter bf2 = new BinaryFormatter();
//レジストリから読み込む
Microsoft.Win32.RegistryKey regkey2 =
    Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
    @"Software\test\subkey", false);
byte[] bs = (byte[]) regkey2.GetValue("Settings");
//逆シリアル化して復元
MemoryStream ms2 = new MemoryStream(bs, false);
appSettings = (Settings) bf2.Deserialize(ms2);
//閉じる
ms2.Close();
regkey2.Close();
}}

***シリアル化の欠点 [#k948c37b]

設定を保存する時、設定オブジェクトをシリアル化して保存するやり方は、簡単、便利である反面、新しくプロパティを加えるとそれ以前に保存したファイルから設定を復元できなくなるという欠点があります。つまり、バージョンアップにより新しい設定が増え、設定クラスに新しいプロパティが増えると、前のバージョンの設定が全く読み込めなくなります。

これを回避するためには、シリアル化せずに一つ一つの設定を保存、復元する、設定をHashtableのようなコレクションで管理する、あるいは、DataSetとして設定を管理し、WriteXml、ReadXmlメソッドで書き込み、読み込みをするなどの方法が考えられます。

***設定をどこに保存するか? [#g749fbfd]

設定を保存する方法をいろいろ紹介しましたが、設定をいったいどのフォルダ、またはレジストリキーに保存するかという問題が残っています。この問題を解決するためのプロパティがApplicationクラスにあります。

設定をレジストリに書き込むとき、書き込むのに適切なレジストリキーは、ApplicationクラスのUserAppDataRegistryまたはCommonAppDataRegistryプロパティで取得できます。

UserAppDataRegistryプロパティは、ユーザー別に設定を保存するために使用します。具体的には、

HKEY_CURRENT_USER\Software\[CompanyName]\[ProductName]\[ProductVersion]

というキーのRegistryKeyオブジェクトを返します([CompanyName]、[ProductName]、[ProductVersion]はそれぞれアプリケーションのCompanyName、ProductName、ProductVersionです)。

CommonAppDataRegistryプロパティは、ユーザー共通の設定を保存するために使用します。具体的には、

HKEY_LOCAL_MACHINE\Software\[CompanyName]\[ProductName]\[ProductVersion]

というキーのRegistryKeyオブジェクトを返します。

つまり、UserAppDataRegistryとCommonAppDataRegistryの違いは、ルートキーがHKEY_CURRENT_USERかHKEY_LOCAL_MACHINEかの違いです。通常のアプリの設定は、UserAppDataRegistryを使って保存すればよいでしょう。

また、設定をファイルに書き込むとき、そのファイルを保存するのに適切なフォルダのパスはApplicationクラスのUserAppDataPath、LocalUserAppDataPath、CommonAppDataPathプロパティで取得できます。

UserAppDataPathプロパティは、ユーザーのアプリケーションデータのパスを返しますので、ユーザー別に設定を保存するために使用します。具体的には、例えば、

C:\Documents and Settings\[UserName]\Application Data\[CompanyName]\[ProductName]\[ProductVersion]

のようなフォルダのパスを返します([UserName]はユーザー名です)。

LocalUserAppDataPathプロパティは、非ローミングユーザーのアプリケーションデータのパスを返します。具体的には、例えば、

C:\Documents and Settings\[UserName]\Local Settings\Application Data\[CompanyName]\[ProductName]\[ProductVersion]

のようなフォルダのパスを返します。

CommonAppDataPathプロパティは、すべてのユーザーが共有する設定を保存するために使用します。具体的には、例えば、

C:\Documents and Settings\All Users\Application Data\[CompanyName]\[ProductName]\[ProductVersion]

のようなフォルダのパスを返します。

通常のアプリの保存先としては、UserAppDataPathプロパティが返すパスを使えばよいでしょう。

ここで紹介したプロパティが返すパスは、すべて最後にアプリのバージョンが付いています。これはつまり、これらをそのまま使って設定を保存すると、バージョンごとに設定の保存先が変わるため、バージョンが変わると、前の設定を読み込めないということになります。これでは困るという時は、保存場所を自分で決めるか、バージョンが変わった時に、前のバージョンの設定を移動するようにするなどの工夫が必要になるでしょう。

補足1:ここで紹介したプロパティから値を取得する時に、そのレジストリキーあるいはフォルダが存在しなかった場合、勝手に作成されます。

補足2:ここで紹介したプロパティは、そのパスにアセンブリの会社名や製品名をそのまま使って生成しているため、アセンブリの会社名や製品名にファイル名として使えない文字が含まれている場合はエラーが発生しますし、"\"が使われている場合は予期せぬパスとなってしまいます。よって、アセンブリの会社名や製品名に不適切な文字が含まれていないことを確かにしてから、これらのプロパティを使用する必要があります。

***まとめ [#j1d752fa]

以上の知識を元にして、Settingsクラスを作り直してみます。

まず、SettingsクラスのインスタンスをSettingsクラスの静的プロパティ"Instance"で取得できるようにします。

さらに、Settingsクラスの静的メソッドにより、XMLファイル、バイナリファイル、さらにレジストリへの設定の保存と復元ができるようにしています。なお保存先のパスは、バージョンに依存しない場所にしています。

#code(vbnet){{
Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Windows.Forms
Imports Microsoft.Win32

<Serializable()> _
Public Class Settings
    '設定を保存するフィールド
    Private _text As String
    Private _number As Integer

    '設定のプロパティ
    Public Property Text() As String
        Get
            Return _text
        End Get
        Set(ByVal Value As String)
            _text = Value
        End Set
    End Property

    Public Property Number() As Integer
        Get
            Return _number
        End Get
        Set(ByVal Value As Integer)
            _number = value
        End Set
    End Property

    'コンストラクタ
    Public Sub New()
        _text = "Text"
        _number = 0
    End Sub

    'Settingsクラスのただ一つのインスタンス
    <NonSerialized()> _
    Private Shared _instance As Settings
    <System.Xml.Serialization.XmlIgnore()> _
    Public Shared Property Instance() As Settings
        Get
            If _instance Is Nothing Then
                _instance = New Settings
            End If
            Return _instance
        End Get
        Set(ByVal Value As Settings)
            _instance = Value
        End Set
    End Property

    ''' <summary>
    ''' 設定をXMLファイルから読み込み復元する
    ''' </summary>
    Public Shared Sub LoadFromXmlFile()
        Dim p As String = GetSettingPath()

        Dim fs As New FileStream( _
            p, FileMode.Open, FileAccess.Read)
        Dim xs As New System.Xml.Serialization.XmlSerializer( _
            GetType(Settings))
        '読み込んで逆シリアル化する
        Dim obj As Object = xs.Deserialize(fs)
        fs.Close()

        Instance = CType(obj, Settings)
    End Sub

    ''' <summary>
    ''' 現在の設定をXMLファイルに保存する
    ''' </summary>
    Public Shared Sub SaveToXmlFile()
        Dim p As String = GetSettingPath()

        Dim fs As New FileStream( _
            p, FileMode.Create, FileAccess.Write)
        Dim xs As New System.Xml.Serialization.XmlSerializer( _
            GetType(Settings))
        'シリアル化して書き込む
        xs.Serialize(fs, Instance)
        fs.Close()
    End Sub

    ''' <summary>
    ''' 設定をバイナリファイルから読み込み復元する
    ''' </summary>
    Public Shared Sub LoadFromBinaryFile()
        Dim p As String = GetSettingPath()

        Dim fs As New FileStream( _
            p, FileMode.Open, FileAccess.Read)
        Dim bf As New BinaryFormatter
        '読み込んで逆シリアル化する
        Dim obj As Object = bf.Deserialize(fs)
        fs.Close()

        Instance = CType(obj, Settings)
    End Sub

    ''' <summary>
    ''' 現在の設定をバイナリファイルに保存する
    ''' </summary>
    Public Shared Sub SaveToBinaryFile()
        Dim p As String = GetSettingPath()

        Dim fs As New FileStream( _
            p, FileMode.Create, FileAccess.Write)
        Dim bf As New BinaryFormatter
        'シリアル化して書き込む
        bf.Serialize(fs, Instance)
        fs.Close()
    End Sub

    ''' <summary>
    ''' 設定をレジストリから読み込み復元する
    ''' </summary>
    Public Shared Sub LoadFromRegistry()
        Dim bf As New BinaryFormatter
        'レジストリから読み込む
        Dim reg As RegistryKey = GetSettingRegistry()
        Dim bs As Byte() = CType(reg.GetValue(""), Byte())
        '逆シリアル化して復元
        Dim ms As New MemoryStream(bs, False)
        Instance = CType(bf.Deserialize(ms), Settings)
        '閉じる
        ms.Close()
        reg.Close()
    End Sub

    ''' <summary>
    ''' 現在の設定をレジストリに保存する
    ''' </summary>
    Public Shared Sub SaveToRegistry()
        Dim ms As New MemoryStream
        Dim bf As New BinaryFormatter
        'シリアル化してMemoryStreamに書き込む
        bf.Serialize(ms, Instance)
        'レジストリへ保存する
        Dim reg As RegistryKey = GetSettingRegistry()
        reg.SetValue("", ms.ToArray())
        '閉じる
        ms.Close()
        reg.Close()
    End Sub

    Private Shared Function GetSettingPath() As String
        Dim p As String = Path.Combine( _
            Environment.GetFolderPath( _
                Environment.SpecialFolder.ApplicationData), _
            Application.CompanyName + "\" + Application.ProductName _
            + "\" + Application.ProductName + ".config")
        Return p
    End Function

    Private Shared Function GetSettingRegistry() As RegistryKey
        Dim reg As RegistryKey = _
            Registry.CurrentUser.CreateSubKey( _
                ("Software\" + Application.CompanyName + _
                "\" + Application.ProductName))
        Return reg
    End Function
End Class
}}

#code(csharp){{
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using Microsoft.Win32;

[Serializable()]
public class Settings
{
    //設定を保存するフィールド
    private string _text;
    private int _number;

    //設定のプロパティ
    public string Text
    {
        get {return _text;}
        set {_text = value;}
    }
    public int Number
    {
        get {return _number;}
        set {_number = value;}
    }

    //コンストラクタ
    public Settings()
    {
        _text = "Text";
        _number = 0;
    }

    //Settingsクラスのただ一つのインスタンス
    [NonSerialized()]
    private static Settings _instance;
    [System.Xml.Serialization.XmlIgnore]
    public static Settings Instance
    {
        get
        {
            if (_instance == null)
                _instance = new Settings();
            return _instance;
        }
        set {_instance = value;}
    }

    /// <summary>
    /// 設定をXMLファイルから読み込み復元する
    /// </summary>
    public static void LoadFromXmlFile()
    {
        string path = GetSettingPath();

        FileStream fs = new FileStream(path,
            FileMode.Open,
            FileAccess.Read);
        System.Xml.Serialization.XmlSerializer xs =
            new System.Xml.Serialization.XmlSerializer(
                typeof(Settings));
        //読み込んで逆シリアル化する
        object obj = xs.Deserialize(fs);
        fs.Close();

        Instance = (Settings) obj;
    }

    /// <summary>
    /// 現在の設定をXMLファイルに保存する
    /// </summary>
    public static void SaveToXmlFile()
    {
        string path = GetSettingPath();

        FileStream fs = new FileStream(path,
            FileMode.Create,
            FileAccess.Write);
        System.Xml.Serialization.XmlSerializer xs =
            new System.Xml.Serialization.XmlSerializer(
            typeof(Settings));
        //シリアル化して書き込む
        xs.Serialize(fs, Instance);
        fs.Close();
    }

    /// <summary>
    /// 設定をバイナリファイルから読み込み復元する
    /// </summary>
    public static void LoadFromBinaryFile()
    {
        string path = GetSettingPath();

        FileStream fs = new FileStream(path,
            FileMode.Open,
            FileAccess.Read);
        BinaryFormatter bf = new BinaryFormatter();
        //読み込んで逆シリアル化する
        object obj = bf.Deserialize(fs);
        fs.Close();

        Instance = (Settings) obj;
    }

    /// <summary>
    /// 現在の設定をバイナリファイルに保存する
    /// </summary>
    public static void SaveToBinaryFile()
    {
        string path = GetSettingPath();

        FileStream fs = new FileStream(path,
            FileMode.Create,
            FileAccess.Write);
        BinaryFormatter bf = new BinaryFormatter();
        //シリアル化して書き込む
        bf.Serialize(fs, Instance);
        fs.Close();
    }

    /// <summary>
    /// 設定をレジストリから読み込み復元する
    /// </summary>
    public static void LoadFromRegistry()
    {
        BinaryFormatter bf = new BinaryFormatter();
        //レジストリから読み込む
        RegistryKey reg = GetSettingRegistry();
        byte[] bs = (byte[]) reg.GetValue("");
        //逆シリアル化して復元
        MemoryStream ms = new MemoryStream(bs, false);
        Instance = (Settings) bf.Deserialize(ms);
        //閉じる
        ms.Close();
        reg.Close();
    }

    /// <summary>
    /// 現在の設定をレジストリに保存する
    /// </summary>
    public static void SaveToRegistry()
    {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();
        //シリアル化してMemoryStreamに書き込む
        bf.Serialize(ms, Instance);
        //レジストリへ保存する
        RegistryKey reg = GetSettingRegistry();
        reg.SetValue("", ms.ToArray());
        //閉じる
        ms.Close();
        reg.Close();
    }

    private static string GetSettingPath()
    {
        string path = Path.Combine(
            Environment.GetFolderPath(
                Environment.SpecialFolder.ApplicationData),
            Application.CompanyName + "\\" + Application.ProductName +
            "\\" + Application.ProductName + ".config");
        return path;
    }

    private static RegistryKey GetSettingRegistry()
    {
        RegistryKey reg = Registry.CurrentUser.CreateSubKey(
            "Software\\" + Application.CompanyName +
            "\\" + Application.ProductName);
        return reg;
    }
}
}}

このクラスを使用して設定をXMLファイルに保存、復元するには、次のようにします。(設定を読み込む時、保存されたデータが無い場合はエラーが出ます。)

#code(vbnet){{
'設定を変更する
Settings.Instance.Number = 123
Settings.Instance.Text = "こんにちは"

'現在の設定をXMLファイルに保存する
Settings.SaveToRegistry()

'XMLファイルから設定を読み込む
Settings.LoadFromRegistry()
}}

#code(csharp){{
//設定を変更する
Settings.Instance.Number = 123;
Settings.Instance.Text = "こんにちは";

//現在の設定をXMLファイルに保存する
Settings.SaveToRegistry();

//XMLファイルから設定を読み込む
Settings.LoadFromRegistry();
}}

***最後に [#nd065cd3]

アプリケーションの設定を保存、復元する方法には、実に様々な方法があり、ここで紹介した以外にもまだまだあるでしょう。ここで紹介した方法よりもよい方法をご存知の方は、ご連絡いただければ幸いです。

参考:

-[[.NET Framework におけるアプリケーション設定の永続化>http://www.microsoft.com/japan/msdn/net/general/persistappsettnet.asp]]

**コメント [#db0d537f]
#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]] [[:Category/ASP.NET]],2010-03-21 (日) 02:10:47,DOBON!,2010-03-21 (日) 02:10:47,DOBON!)
#pageinfo([[:Category/.NET]],2004-05-18 (火) 06:00:00,DOBON!,2010-03-21 (日) 02:10:54,DOBON!)

[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]