はじめに
アプリケーションの設定値 (フォームの位置やサイズなど) を保存し, 次回起動時にこの設定値で起動する、ということを実施することがあると思います. この設定値を保存する形式は, .NET Frameworkアプリケーションではxml形式が推奨されていますが, 未だにini形式が好まれたりします.
そのため, iniファイルの読み書き用のクラスを作成してみました.
NativeMethods
使用するWin32 APIの定義はNativeMethodsクラスに以下のように定義します.
NativeMethods.cs
using System.Text;
using System.Runtime.InteropServices;
internal sealed class NativeMethods
{
private NativeMethods() { }
[DllImport("kernel32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi, ExactSpelling = false)]
internal static extern uint GetPrivateProfileString(
[MarshalAs(UnmanagedType.LPWStr), In] string lpAppName,
[MarshalAs(UnmanagedType.LPWStr), In] string lpKeyName,
[MarshalAs(UnmanagedType.LPWStr), In] string lpDefault,
[MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder lpReturnString,
uint nSize,
[MarshalAs(UnmanagedType.LPWStr), In] string iniFilename);
[DllImport("kernel32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
internal static extern int WritePrivateProfileString(
[MarshalAs(UnmanagedType.LPWStr), In] string lpAppName,
[MarshalAs(UnmanagedType.LPWStr), In] string lpKeyName,
[MarshalAs(UnmanagedType.LPWStr), In] string lpString,
[MarshalAs(UnmanagedType.LPWStr), In] string lpFileName);
}
Iniクラス
iniファイル読み書き用のクラスは次の通りです.
Ini
using System;
using System.ComponentModel;
using System.IO;
using System.Text;
public static class Ini
{
/// <summary>
/// INIファイルからキーの値を取得します
/// <para>戻り値は, 取得が成功したかどうかを示します</para>
/// </summary>
/// <typeparam name="T">データ取得する型</typeparam>
/// <param name="filePath">ファイルパス</param>
/// <param name="sectionName">セクション名</param>
/// <param name="keyName">キー名</param>
/// <param name="defaultValue">初期値</param>
/// <param name="outputValue">出力値</param>
/// <returns>取得の成功有無</returns>
public static bool TryGetValueOrDefault<T>(string filePath, string sectionName, string keyName, T defaultValue, out T outputValue)
{
outputValue = defaultValue;
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
return false;
var sb = new StringBuilder(1024);
var ret = NativeMethods.GetPrivateProfileString(sectionName, keyName, string.Empty, sb, Convert.ToUInt32(sb.Capacity), filePath);
if (ret == 0 || string.IsNullOrEmpty(sb.ToString()))
return false;
var conv = TypeDescriptor.GetConverter(typeof(T));
if (conv == null)
return false;
try
{
outputValue = (T)conv.ConvertFromString(sb.ToString());
}
catch (NotSupportedException)
{
return false;
}
catch (FormatException)
{
return false;
}
return true;
}
/// <summary>
/// INIファイルからキーの値を取得します
/// </summary>
/// <typeparam name="T">データ取得する型</typeparam>
/// <param name="filePath">ファイルパス</param>
/// <param name="sectionName">セクション名</param>
/// <param name="keyName">キー名</param>
/// <param name="defaultValue">初期値</param>
/// <returns>キー値</returns>
public static T GetValueOrDefault<T>(string filePath, string sectionName, string keyName, T defaultValue)
{
T ret = defaultValue;
TryGetValueOrDefault(filePath, sectionName, keyName, defaultValue, out ret);
return ret;
}
/// <summary>
/// INIファイルにデータを書き込みます
/// </summary>
/// <param name="filePath">ファイルパス</param>
/// <param name="sectionName">セクション名</param>
/// <param name="keyName">キー名</param>
/// <param name="outputValue">出力値</param>
public static void SetValue(string filePath, string sectionName, string keyName, string outputValue) =>
NativeMethods.WritePrivateProfileString(sectionName, keyName, outputValue, filePath);
}
使い方
WinFormsアプリケーションでフォームの位置・サイズをiniファイルへの読み書きするサンプルです.
アプリケーションと同一ディレクトリーにTest.iniが存在しているとし, このTest.iniに設定値を読み書きします. FormのLoadイベントでiniファイルの内容を読み込み, FormClosingイベントでiniファイルに書き込みしています.
サンプルアプリ
private void MainForm_Load(object sender, EventArgs e)
{
StartPosition = FormStartPosition.Manual;
//iniから前回のフォーム位置、サイズ取得
var filePath = System.IO.Path.Combine(Environment.CurrentDirectory, "Test.ini");
Left = Ini.GetValueOrDefault(filePath, Name, nameof(Left), 0);
Top = Ini.GetValueOrDefault(filePath, Name, nameof(Top), 0);
Width = Ini.GetValueOrDefault(filePath, Name, nameof(Width), 100);
Height = Ini.GetValueOrDefault(filePath, Name, nameof(Height), 100);
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
//iniにフォーム位置、サイズ保存
var filePath = System.IO.Path.Combine(Environment.CurrentDirectory, "Test.ini");
Ini.SetValue(filePath, Name, nameof(Left), Left.ToString());
Ini.SetValue(filePath, Name, nameof(Top), Top.ToString());
Ini.SetValue(filePath, Name, nameof(Width), Width.ToString());
Ini.SetValue(filePath, Name, nameof(Height), Height.ToString());
}
最後に
今回作成したIniクラスを使用することで簡易にiniファイルの内容を読み書きできるようになりました.