Jeff Danner
Microsoft Corporation
June 2002
日本語版最終更新日 2002 年 8 月 28 日
要約 : レジストリに設定を保存するか、構成ファイルにシリアル化することによって、実行時に Microsoft .NET Framework のアプリケーション設定を保持する方法を説明します。
目次
はじめに
アプリケーション設定保存の前提条件
レジストリを使用してデータを保存する
レジストリにデータを保存する
レジストリからデータを取得する
カスタム アプリケーション構成クラスを作成する
アプリケーションで設定クラスを使用する
保存したアプリケーション設定を読み込む
アプリケーション設定を保存する
まとめ
はじめに
アプリケーション設定の保存は頻繁に実行する一般的なタスクです。以前は、INI ファイルまたはレジストリに保存していました。Microsoft® .NET Framework ではその方法に加え、アプリケーション設定を XML ファイルにシリアル化して、容易に設定の更新および取得を実行できます。Microsoft Visual Studio® .NET では System.Configuration.AppSettingsReader クラスを使用して、その DynamicProperties を読み取ります。これは構成ファイルに格納されています。しかし、実行時の動的プロパティは読み取り専用であるため、ユーザーが加えた変更を保持できません。この記事では、データをシリアル化してファイルに書き出す方法、および読み取ってシリアル化を解除する方法を説明します。データを保存する方法と場所は格納する対象で決まります。格納するデータの型に基づいて、適切な場所に保存する方法についても説明します。
アプリケーション設定保存の前提条件
Windows フォームの Application クラスには複数のプロパティが含まれており、これらを使用すればレジストリやユーザー データ フォルダの適切な場所へ容易に移動できます。これらのプロパティを正しく使用するには、AssemblyCompany、AssemblyProduct、AssemblyVersion の各属性を設定する必要があります。
これらの属性では、それぞれ CompanyName、ProductName、および ProductVersion の各プロパティから Control クラスによって取得された値が設定されます。
次のコードは簡単な Windows フォームの例です。これはアセンブリ属性を設定して、ラベルに表示します。
' Visual Basic
Imports System
Imports System.Windows.Forms
Imports System.Reflection
' アセンブリ属性を設定します。
<Assembly: AssemblyCompany("Microsoft")>
<Assembly: AssemblyProduct("MyApplication")>
<Assembly: AssemblyVersion("1.0.1")>
Public Class AboutDialogBox
Inherits Form
Public Sub New()
' アセンブリ情報をラベルに表示します。
Dim label1 As New Label()
label1.Text = _
Me.CompanyName + " " + _
Me.ProductName + " バージョン: " + _
Me.ProductVersion
label1.AutoSize = True
Me.Controls.Add(label1)
End Sub
End Class
//C#
using System;
using System.Windows.Forms;
using System.Reflection;
// アセンブリ属性を設定します。
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("MyApplication")]
[assembly: AssemblyVersion("1.0.1")]
public class AboutDialogBox : Form
{
public AboutDialogBox()
{
// アセンブリ情報をラベルに表示します。
Label label1 = new Label();
label1.Text = this.CompanyName + " "
+ this.ProductName + " バージョン: "
+ this.ProductVersion;
label1.AutoSize = true;
this.Controls.Add(label1);
}
[STAThread]
static void Main()
{
Application.Run(new AboutDialogBox());
}
}
レジストリを使用してデータを保存する
アプリケーションにとって重要で機密性の高いデータを単純にシリアル化すると、誰でもそれを見てテキスト エディタで編集できるので、レジストリを使用してデータへのアクセスを制限します。レジストリであれば、アプリケーションとユーザーの設定を安全に格納できます。ほとんどのバックアップ プログラムはレジストリ設定を自動的にバックアップします。また設定を格納するとき、レジストリの適切な場所にデータを置けば、ユーザーどうしを自動的に分離できます。ユーザーがレジストリを編集することは可能ですが、一般的には実行するユーザーはほとんどいないので、設定は安全であると言えます。レジストリの使用方法に関する Microsoft Windows® ロゴ ガイドラインに従っていれば、アプリケーション設定の格納場所としてはレジストリが妥当です。
レジストリへの書き込みには、アプリケーションにレジストリの作成権限と書き込み権限が必要であり、読み取りには読み取り権限が必要です。レジストリ キーの詳細については、Microsoft.Win32.RegistryKey クラスの GetValue メソッドと SetValue メソッドに関するドキュメント、および .NET Framework SDK ドキュメントの System.Security.Permissions.RegistryPermissionAccess の列挙に関するドキュメントを参照してください。
データをレジストリに保存するには、Application クラスの UserAppDataRegistry プロパティまたは CommonAppDataRegistry プロパティを使用します。これらのプロパティは、ユーザー タイプに基づいて、アプリケーション データ保存に使用する RegistryKey オブジェクトを返します。
- UserAppDataRegistry プロパティは、各ユーザーの移動データ (ユーザー固有であるがコンピュータには依存しないデータ) の保存に使用するレジストリ キーを返します。レジストリ キーは、HKEY_CURRENT_USER\Software\[Control.CompanyName]\[Control.ProductName]\[Control.ProductVersion] の形式です。
- CommonAppDataRegistry プロパティは、ユーザーに依存しない、そのコンピュータにとっては非移動データの保存に使用するレジストリ キーを返します。レジストリ キーは、HKEY_LOCAL_MACHINE\Software\[Control.CompanyName]\[Control.ProductName]\[Control.ProductVersion] の形式です。
この 2 つのプロパティは読み取り専用です。ただし、返される RegistryKey オブジェクトには、レジストリ キーとその値の読み取り、更新、作成を可能にするメソッドがいくつか含まれています。
レジストリにデータを保存する
次のコードは、接続文字列が変更された場合、フォームを終了するときにそれをレジストリに保存する例です。
' Visual Basic
Private appSettingsChanged As Boolean
Private connectionString As String
Private Sub Form1_Closing(sender As Object,
e As CancelEventArgs) Handles MyBase.Closing
If appSettingsChanged Then
Try
' 接続文字列が変更されている場合、それをレジストリに保存します。
Application.UserAppDataRegistry.SetValue("ConnString", _
connectionString)
Catch ex As Exception
MessageBox.Show(ex.Message )
End Try
End If
End Sub
// C#
private bool appSettingsChanged;
private string connectionString;
private void Form1_Closing(object sender, CancelEventArgs e)
{
if(appSettingsChanged)
{
try
{
// 接続文字列が変更されている場合、それをレジストリに保存します。
Application.UserAppDataRegistry.SetValue("ConnString",
connectionString);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message );
}
}
}
レジストリからデータを取得する
以下のコードは、フォームを読み込むときに接続文字列をレジストリから取得する例です。
' Visual Basic
Private appSettingsChanged As Boolean
Private connectionString As String
Private Sub Form1_Load(sender As Object,
e As EventArgs) Handles MyBase.Load
Try
' レジストリから接続文字列を取得します。
If Not (Application.UserAppDataRegistry.GetValue("ConnString") _
Is Nothing) Then
connectionString = _
Application.UserAppDataRegistry.GetValue( _
"ConnString").ToString()
statusBar1.Text = "接続文字列: " + connectionString
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
// C#
private bool appSettingsChanged;
private string connectionString;
private void Form1_Load(object sender, EventArgs e)
{
try
{
// レジストリから接続文字列を取得します。
if(Application.UserAppDataRegistry.GetValue("ConnString") != null)
{
connectionString =
Application.UserAppDataRegistry.GetValue(
"ConnString").ToString();
statusBar1.Text = "接続文字列: " +
connectionString;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
カスタム アプリケーション構成クラスを作成する
この記事で説明するアプリケーション構成クラスは、自身のインスタンスを XML としてシリアル化します。シリアル化とは、オブジェクトまたはオブジェクトのグラフィックを別の場所に保存または転送するために、バイトの連続シーケンスに変換する処理のことです。シリアル化解除は、保存または転送されたデータを取り込み、オブジェクトを再生する処理です。オブジェクトは、テキスト (XML は階層構造のテキスト) 形式またはバイナリ形式でシリアル化できます。シリアル化の詳細については、.NET Framework Developer's Guide の 「オブジェクトのシリアル化」 を参照してください。
コントロールから派生した Windows フォームのクラスを XML としてシリアル化するのは容易ではありません。これは、ウィンドウ ハンドル (HWND) など、動的なステータスを持つオブジェクトが含まれているためです。コントロール全体のシリアル化は容易ではなく、またコントロールによって取得されるすべてのプロパティを保持することも通常は必要ないため、小さな XML シリアル化可能クラスを作成して必要なプロパティ値を格納します。たとえば、フォームの BackColor、ユーザーが最後にファイルを保存したディレクトリ、または前回フォームを終了したときのそのフォームの Location のみを保存する場合を考えます。XML ファイルの作成と書き込みには、アプリケーションに書き込み権限が必要であり、読み取りには読み取り権限が必要です。詳細については、.NET Framework SDK の 「StreamWriter コンストラクタ」 および System.Security.Permissions.FileIOPermissionAccess の列挙に関するドキュメントを参照してください。型によっては、先に変換しないと XML にシリアル化できないものがあります。たとえば、System.Drawing.Color は、その ToArgb メソッドを使用して、XML にシリアル化できる整数に変換する必要があります。型変換機能は、文字列表現への変換にも使用できます。型変換機能の詳細については、.NET Framework SDK ドキュメントの 「TypeConverter クラス」 および 「型コンバータの実装」 を参照してください。
Application クラスのプロパティの中には、アプリケーション データを保存するためのアプリケーション保存パスを提供するものがあります。
- UserAppDataPath プロパティは、各ユーザーの移動データ (ユーザー固有であるがコンピュータには依存しないデータ) の保存で使用します。パスは、[UserName]\Application Data\[Control.CompanyName]\[Control.ProductName]\[Control.ProductVersion] の形式です。
- LocalUserAppDataPath プロパティは、各ユーザーの非移動データの保存で使用します。パスは、[UserName]\Local Settings\Application Data\[Control.CompanyName]\[Control.ProductName]\[Control.ProductVersion] の形式です。
- CommonAppDataPath プロパティは、ユーザーに依存せずコンピュータにとって非移動データの保存で使用します。パスは、All Users\Application Data\[Control.CompanyName]\[Control.ProductName]\[Control.ProductVersion] の形式です。
注 :
データ パスに使用する UserName の値は、System.Environment クラスの UserName プロパティから取得します。
通常、移動データとして保存されるのは、ウィンドウの設定などの小さいデータです。一方、非移動データとして格納されるのは、大きなビットマップのキャッシュなど、大きいデータです。
次のコードは、アプリケーションの設定を保存するクラスを含む例です。このクラスは、アプリケーション設定の読み込み (シリアル化解除) と保存 (シリアル化) に使用する SaveAppSettings メソッドと LoadAppSettings メソッドを提供します。BackColor プロパティの値は、シリアル化が可能なように整数として格納されています。この例では、シリアル化データを MyApplication.config ファイルに保存します。これは、Visual Studio .NET で使用する App.config ファイルとは異なります。
- クラスを作成し、アプリケーション設定が変更されたかどうかを示すブール変数を追加します。System.Xml.Serialization と System.IO の両名前空間への参照、およびデータの保存に必要なその他の名前空間への参照を必ず追加します。
' Visual Basic
Imports System
Imports System.Xml.Serialization
Imports System.IO
Imports System.Drawing
Namespace Samples
Public Class ApplicationSettings
Private appSettingsChanged As Boolean
End Class
End Namespace
// C#
using System;
using System.Xml.Serialization;
using System.IO;
using System.Drawing;
namespace Samples
{
public class ApplicationSettings
{
private bool appSettingsChanged;
}
}
- アプリケーション設定を保存するためのプライベート変数を追加し、それにアクセスするためのパブリック プロパティを作成します。
' Visual Basic
' アプリケーション設定の保存に使用する変数。
Private m_defaultDirectory As String
Private m_backColor As Integer
Private m_formLocation As Point
' アプリケーション設定変数へのアクセスに使用するプロパティ。
Public Property DefaultDirectory() As String
Get
Return m_defaultDirectory
End Get
Set
If value <> m_defaultDirectory Then
m_defaultDirectory = value
appSettingsChanged = True
End If
End Set
End Property
Public Property BackColor() As Integer
Get
Return m_backColor
End Get
Set
If value <> m_backColor Then
m_backColor = value
appSettingsChanged = True
End If
End Set
End Property
Public Property FormLocation() As Point
Get
Return m_formLocation
End Get
Set
If Not value.Equals(m_formLocation) Then
m_formLocation = value
appSettingsChanged = True
End If
End Set
End Property
// C#
// アプリケーション設定の保存に使用する変数。
private string m_defaultDirectory;
private int m_backColor;
private Point m_formLocation;
// アプリケーション設定変数へのアクセスに使用するプロパティ。
public string DefaultDirectory
{
get{return m_defaultDirectory;}
set
{
if(value != m_defaultDirectory)
{
m_defaultDirectory = value;
appSettingsChanged = true;
}
}
}
public int BackColor
{
get{return m_backColor;}
set
{
if(value != m_backColor)
{
m_backColor = value;
appSettingsChanged = true;
}
}
}
public Point FormLocation
{
get{return m_formLocation;}
set
{
if(value != m_formLocation)
{
m_formLocation = value;
appSettingsChanged = true;
}
}
}
- アプリケーション設定をシリアル化して構成ファイルに保存するメソッドを追加します。
' Visual Basic
' 変更されている設定がある場合、クラスを
' 構成ファイルにシリアル化します。
Public Function SaveAppSettings() As Boolean
If Me.appSettingsChanged Then
Dim myWriter As StreamWriter = Nothing
Dim mySerializer As XmlSerializer = Nothing
Try
' ApplicationSettings 型の
' XmlSerializer を作成します。
mySerializer = New XmlSerializer( _
GetType(ApplicationSettings))
myWriter = New StreamWriter( _
Application.LocalUserAppDataPath + _
"\myApplication.config", False)
' ApplicationSettings クラスのこのインスタンスを
' 構成ファイルにシリアル化します。
mySerializer.Serialize(myWriter, Me)
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
' FileStream が開いている場合は閉じます。
If Not (myWriter Is Nothing) Then
myWriter.Close()
End If
End Try
End If
Return appSettingsChanged
End Function
// C#
// 変更されている設定がある場合、クラスを
// 構成ファイルにシリアル化します。
public bool SaveAppSettings()
{
if(this.appSettingsChanged)
{
StreamWriter myWriter = null;
XmlSerializer mySerializer = null;
try
{
// ApplicationSettings 型の
// XmlSerializer を作成します。
mySerializer = new XmlSerializer(
typeof(ApplicationSettings));
myWriter =
new StreamWriter(Application.LocalUserAppDataPath
+ @"\myApplication.config",false);
// ApplicationSettings クラスのこのインスタンスを
// 構成ファイルにシリアル化します。
mySerializer.Serialize(myWriter, this);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// FileStream が開いている場合は閉じます。
if(myWriter != null)
{
myWriter.Close();
}
}
}
return appSettingsChanged;
}
- 構成ファイルからアプリケーション設定をシリアル化解除するメソッドを追加します。
' Visual Basic
' 構成ファイルからクラスをシリアル化解除します。
Public Function LoadAppSettings() As Boolean
Dim mySerializer As XmlSerializer = Nothing
Dim myFileStream As FileStream = Nothing
Dim fileExists As Boolean = False
Try
' ApplicationSettings 型の XmlSerializer を作成します。
mySerializer = New XmlSerializer(GetType(ApplicationSettings))
Dim fi As New FileInfo(Application.LocalUserAppDataPath + _
"\myApplication.config")
' 構成ファイルが存在する場合は、それを開きます。
If fi.Exists Then
myFileStream = fi.OpenRead()
' 構成ファイルをシリアル化解除することにより、
' ApplicationSettings の新規インスタンスを作成します。
Dim myAppSettings As ApplicationSettings = CType( _
mySerializer.Deserialize(myFileStream), _
ApplicationSettings)
' ApplicationSettings クラスのこのインスタンスに
' プロパティ値を割り当てます。
Me.m_backColor = myAppSettings.BackColor
Me.m_formLocation = myAppSettings.FormLocation
Me.m_defaultDirectory = myAppSettings.DefaultDirectory
fileExists = True
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
' FileStream が開いている場合は閉じます。
If Not (myFileStream Is Nothing) Then
myFileStream.Close()
End If
End Try
' myDirectory が設定されていない場合、既定値として
' ユーザーのマイ ドキュメント ディレクトリを使用します。
If m_defaultDirectory Is Nothing Then
m_defaultDirectory = Environment.GetFolderPath( _
System.Environment.SpecialFolder.Personal)
Me.appSettingsChanged = True
End If
Return fileExists
End Function
// C#
// 構成ファイルからクラスをシリアル化解除します。
public bool LoadAppSettings()
{
XmlSerializer mySerializer = null;
FileStream myFileStream = null;
bool fileExists = false;
try
{
// ApplicationSettings 型の XmlSerializer を作成します。
mySerializer = new XmlSerializer(typeof(ApplicationSettings));
FileInfo fi = new FileInfo(Application.LocalUserAppDataPath
+ @"\myApplication.config");
// 構成ファイルが存在する場合は、それを開きます。
if(fi.Exists)
{
myFileStream = fi.OpenRead();
// 構成ファイルをシリアル化解除することにより、
// ApplicationSettings の新規インスタンスを作成します。
ApplicationSettings myAppSettings =
(ApplicationSettings)mySerializer.Deserialize(
myFileStream);
// ApplicationSettings クラスのこのインスタンスに
// プロパティ値を割り当てます。
this.m_backColor = myAppSettings.BackColor;
this.m_formLocation = myAppSettings.FormLocation;
this.m_defaultDirectory = myAppSettings.DefaultDirectory;
fileExists = true;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// FileStream が開いている場合は閉じます。
if(myFileStream != null)
{
myFileStream.Close();
}
}
if(m_defaultDirectory == null)
{
// myDirectory が設定されていない場合、既定値として
// ユーザーのマイ ドキュメント ディレクトリを使用します。
m_defaultDirectory = Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
this.appSettingsChanged = true;
}
return fileExists;
}
アプリケーションで設定クラスを使用する
アプリケーション設定クラスを使用して、設定を保持する値をシリアル化およびシリアル化解除するには、コードに数行を追加するだけです。
保存したアプリケーション設定を読み込む
アプリケーションを保存するように定義した型の変数を用意する必要があります。この例では、applicationSettings という名前の付いた ApplicationSettings クラスです。コード内の適切な位置で、データをシリアル化解除するメソッドを呼び出します。この例では LoadAppSettings() メソッドを、フォームの Load イベントで呼び出しています。このメソッドは、他の任意の初期化コードに続くコンストラクタや、Load イベント ハンドラからでも呼び出せます。次に、格納した値をアプリケーションの該当プロパティに割り当てます。
次のコードは、アプリケーション設定をフォームの Load イベントで読み込み、値を該当プロパティに割り当てる例です。この例ではフォームに defaultDirectory という変数があることを前提としています。
' Visual Basic
' LoadAppSettings メソッドが正常に終了すると、ApplicationSettings
' プロパティをフォームの該当プロパティに割り当てます。
Private Sub Form1_Load(sender As Object, _
e As EventArgs) Handles MyBase.Load
If applicationSettings.LoadAppSettings() Then
' 整数 (ARGB) 値から Color を作成します。
Me.BackColor = Color.FromArgb(applicationSettings.BackColor)
Me.Location = applicationSettings.FormLocation
Me.defaultDirectory = applicationSettings.DefaultDirectory
End If
End Sub
// C#
// LoadAppSettings メソッドが正常に終了すると、ApplicationSettings
// プロパティをフォームの該当プロパティに割り当てます。
private void Form1_Load(object sender, EventArgs e)
{
if(this.applicationSettings.LoadAppSettings() )
{
// 整数 (ARGB) 値から Color を作成します。
this.BackColor = Color.FromArgb(applicationSettings.BackColor);
this.Location = applicationSettings.FormLocation;
this.defaultDirectory = applicationSettings.DefaultDirectory;
}
}
アプリケーション設定を保存する
アプリケーションを保存するように定義した型の変数を用意する必要があります。この例では、applicationSettings という名前の付いた ApplicationSettings クラスです。コード内の適切な位置で、設定を保持するプロパティ値をアプリケーション設定クラスの該当プロパティに割り当てます。設定を保持しているプロパティに BackColorChanged イベントのような変更されたイベントがある場合は、そのイベント ハンドラでアプリケーション設定クラスの該当プロパティを更新できます。これにより、ユーザーまたはアプリケーションがプロパティを変更するたびに、アプリケーション設定クラスのインスタンスが更新されます。
アプリケーションを終了する前に、データをシリアル化するメソッドを呼び出します。この例では SaveAppSettings() メソッドを、フォームの Closing イベントで呼び出しています。このメソッドを Closing イベント ハンドラで呼び出すか、アプリケーション設定を保存するかどうかを指定したブール値を受け取る Close メソッドをオーバーロードできます。
次のコードは、アプリケーション設定クラスのプロパティを更新して、フォームの Closing イベントでアプリケーション設定を保存する例です。
' Visual Basic
' 場所が変更された場合は、ApplicationSettings
' オブジェクトにそれを保存します。
Private Sub Form1_LocationChanged(sender As Object, _
e As EventArgs) Handles MyBase.LocationChanged
applicationSettings.FormLocation = Me.Location
End Sub
' BackColor が変更された場合は、ApplicationSettings
' オブジェクトにそれを保存します。
Private Sub Form1_BackColorChanged(sender As Object, _
e As EventArgs) Handles MyBase.BackColorChanged
applicationSettings.BackColor = Me.BackColor.ToArgb()
End Sub
' クラス設定をシリアル化してフォームを終了する前に、新規の
' 既定ディレクトリを ApplicationSettings オブジェクトに保存します。
Private Sub Form1_Closing(sender As Object, _
e As CancelEventArgs) Handles MyBase.Closing
applicationSettings.DefaultDirectory = Me.defaultDirectory
applicationSettings.SaveAppSettings()
End Sub
// C#
// 場所が変更された場合は、ApplicationSettings
// オブジェクトにそれを保存します。
private void Form1_LocationChanged(object sender, EventArgs e)
{
applictionSettings.FormLocation = this.Location;
}
// BackColor が変更された場合は、ApplicationSettings
// オブジェクトにそれを保存します。
private void Form1_BackColorChanged(object sender, EventArgs e)
{
applicationSettings.BackColor = this.BackColor.ToArgb();
}
// クラス設定をシリアル化してフォームを終了する前に、新規の
// 既定ディレクトリを ApplicationSettings オブジェクトに保存します。
private void Form1_Closing(object sender, CancelEventArgs e)
{
applicationSettings.DefaultDirectory = this.defaultDirectory;
applicationSettings.SaveAppSettings();
}
まとめ
従来同様、適切なアクセス権限があればレジストリに対する読み書きが可能です。ただし、レジストリに保存するデータの量は制限する必要があります。.NET Framework では最小限の実装とカスタマイズのみで、容易にアプリケーション設定をシリアル化し、データを XML として保存できます。Visual Studio .NET のアプリケーション設定モデルとは異なり、シリアル化データは読んだり更新することが可能です。
このドキュメントで使用されているアプリケーション データおよびレジストリ データのパスは、Windows ロゴ ガイドラインに準拠しています。アプリケーションが Windows ロゴ ガイドラインに準拠しているかどうかを確認するには、Microsoft Windows ロゴ プログラムの Web サイトにある 「ソフトウェア用 "Designed for Windows XP"」 を参照してください。