프로그램의 상태를 저장하는 방법으로 INI를 많이 사용합니다. INI는 사용이 간편하고 초기화가 쉽기 때문에 많이 사용하지만 암호화가 제외된 만큼 보안에 취약하기도 합니다. 하지만 간단한 프로그램에서는 여전히 유용한 기능이니 알아두시면 좋습니다.
✅ INI 설정파일
C#에서 INIManger라는 Class로 .ini 파일을 관리하는 방법입니다.
INI를 사용하기 위해 WINApi의 kernel32.dll 를 사용합니다.
우선 Kernel32Handler 라는 클래스를 만듭니다.
클래스명과 같은 파일명으로 생성합니다.
Kernel32Handler.cs
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace INI
{
public class Kernel32Handler
{
[DllImport("kernel32.dll")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32.dll")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
[DllImport("kernel32")]
public static extern Int32 GetLastError();
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern Int32 FormatMessage(Int32 dwFlags, IntPtr lpSource, Int32 dwMessageId, Int32 dwLanguageId, out String lpBuffer, Int32 dwSize, IntPtr lpArguments);
private static string GetErrorMessage(Int32 errcode)
{
FormatMessage(0x1300, IntPtr.Zero, errcode, 0x400, out String errmsg, 260, IntPtr.Zero);
return errmsg;
}
public static bool SetINI(string path, string section, string key, string value, ref string errMessage)
{
try
{
if(string.IsNullOrEmpty(key) == true)
{
key = "";
}
if(string.IsNullOrEmpty(value) == true)
{
value = "";
}
long result = WritePrivateProfileString(section, key, value, path);
if(result != 0)
{
return true;
}
Int32 errcode = GetLastError();
errMessage = string.Format("{0} : {1}", errcode, GetErrorMessage(errcode));
}
catch (Exception ex)
{
errMessage = ex.Message;
}
return false;
}
public static bool GetINI(string path, string section, string key, int size, ref string value, ref string errMessage)
{
try
{
StringBuilder STBD = new StringBuilder(10000);
GetPrivateProfileString(section, key, null, STBD, size, path);
string val = STBD.ToString().Trim();
if (!string.IsNullOrEmpty(val))
{
value = val;
}
return true;
}
catch (Exception ex)
{
errMessage = ex.Message;
}
return false;
}
}
}
위 Kernel32Handler 클래스를 사용할 INIManager 클래스를 만듭니다.
INIManager.cs
using System;
using System.IO;
namespace INI
{
public static class INIManager
{
public static readonly string AppPath = System.IO.Path.Combine(Environment.CurrentDirectory, "ini", "config.ini");
public static void Set(string section, string key, string value)
{
try
{
if (!File.Exists(AppPath))
{
string dir = System.IO.Path.GetDirectoryName(AppPath);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
FileStream stream = File.Create(AppPath);
stream.Close();
}
string errMessage = "";
Kernel32Handler.SetINI(AppPath, section, key, value, ref errMessage);
}
catch (Exception)
{
}
}
public static bool Get(string section, string key, ref string value, ushort size = 1000)
{
if (string.IsNullOrEmpty(section) || string.IsNullOrEmpty(key))
{
return false;
}
string errMessage = "";
return Kernel32Handler.GetINI(AppPath, section, key, size, ref value, ref errMessage);
}
public static void Get(string section, string key, ref int value)
{
string val = "";
if (Get(section, key, ref val))
{
if (int.TryParse(val, out int result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref ushort value)
{
string val = "";
if (Get(section, key, ref val))
{
if (ushort.TryParse(val, out ushort result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref bool value)
{
string val = "";
if (Get(section, key, ref val))
{
if (bool.TryParse(val, out bool result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref TimeSpan value)
{
string val = "";
if (Get(section, key, ref val))
{
if (TimeSpan.TryParse(val, out TimeSpan result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref DateTime value)
{
string val = "";
if (Get(section, key, ref val))
{
if (DateTime.TryParse(val, out DateTime result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref char value)
{
string val = "";
if (Get(section, key, ref val))
{
if(val == "\\t")
{
val = "\t";
}
if (char.TryParse(val, out char result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref long value)
{
string val = "";
if (Get(section, key, ref val))
{
if (long.TryParse(val, out long result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref double value)
{
string val = "";
if (Get(section, key, ref val))
{
if (double.TryParse(val, out double result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref float value)
{
string val = "";
if (Get(section, key, ref val))
{
if (float.TryParse(val, out float result))
{
value = result;
}
}
}
public static void Get(string section, string key, ref uint value)
{
string val = "";
if (Get(section, key, ref val))
{
if (uint.TryParse(val, out uint result))
{
value = result;
}
}
}
}
}
ini가 저장되는 경로는 AppPath입니다.
Set() 함수는 section명으로 key와 value를 저장하며
Get() 함수의 Argument Type에 따라 ini의 string을 형변환하여 반환합니다.
✅ INI 설정파일 - 끝