Click here to Skip to main content
Click here to Skip to main content

An INI file handling class using C#

By , 14 Mar 2002
 

Introduction

I created a C# class Ini which exposes 2 functions from KERNEL32.dll. These functions are: WritePrivateProfileString and GetPrivateProfileString

Namespaces you will need: System.Runtime.InteropServices and System.Text

The Class

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace Ini
{
    /// <summary>
    /// Create a New INI file to store or load data
    /// </summary>
    public class IniFile
    {
        public string path;

        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section,
            string key,string val,string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section,
                 string key,string def, StringBuilder retVal,
            int size,string filePath);

        /// <summary>
        /// INIFile Constructor.
        /// </summary>
        /// <PARAM name="INIPath"></PARAM>
        public IniFile(string INIPath)
        {
            path = INIPath;
        }
        /// <summary>
        /// Write Data to the INI File
        /// </summary>
        /// <PARAM name="Section"></PARAM>
        /// Section name
        /// <PARAM name="Key"></PARAM>
        /// Key Name
        /// <PARAM name="Value"></PARAM>
        /// Value Name
        public void IniWriteValue(string Section,string Key,string Value)
        {
            WritePrivateProfileString(Section,Key,Value,this.path);
        }
        
        /// <summary>
        /// Read Data Value From the Ini File
        /// </summary>
        /// <PARAM name="Section"></PARAM>
        /// <PARAM name="Key"></PARAM>
        /// <PARAM name="Path"></PARAM>
        /// <returns></returns>
        public string IniReadValue(string Section,string Key)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(Section,Key,"",temp, 
                                            255, this.path);
            return temp.ToString();

        }
    }
}

Using the class

Steps to use the Ini class:

  1. In your project namespace definition add 
    using INI;
  2. Create a INIFile like this
    INIFile ini = new INIFile("C:\\test.ini");
  3. Use IniWriteValue to write a new value to a specific key in a section or use IniReadValue to read a value FROM a key in a specific Section.

That's all. It's very easy in C# to include API functions in your class(es).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

BLaZiNiX
Web Developer
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberjai_magical16 Apr '13 - 11:40 
Easy to understand.
GeneralMy vote of 5memberSaravanan.rex5 Sep '12 - 4:00 
my long time issue of saving config solved Smile | :)
GeneralRe: My vote of 5memberHeadzup27 Sep '12 - 2:16 
for me it dont work on Windows 8 Frown | :( the Program don't create the ini file
GeneralRe: My vote of 5memberSaravanan.rex27 Sep '12 - 7:23 
i am using windows 7. please check the file path . use absolute path like @c:\temp.ini. if you put only file name then it's not creating ini file.
QuestionFormClosingmemberpaphnuty27 Aug '12 - 21:38 
The Closing event is obsolete in the .NET Framework version 2.0; use the FormClosing event in example instead.
Questionmy vote of 5membervelt_99124 Apr '12 - 21:09 
this is awesome..very comprehensive...thanks...
 

and easy to use..Cheers!
QuestionIf you want to support unicode, use this.memberchozekun12 Mar '12 - 21:11 
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
 
/// <summary>
/// Create a New INI file to store or load data
/// </summary>
public class IniFile
{
    [DllImport("KERNEL32.DLL", EntryPoint = "GetPrivateProfileStringW",
    SetLastError = true,
    CharSet = CharSet.Unicode, ExactSpelling = true,
    CallingConvention = CallingConvention.StdCall)]
    private static extern int GetPrivateProfileString(
      string lpSection,
      string lpKey,
      string lpDefault,
      StringBuilder lpReturnString,
      int nSize,
      string lpFileName);
 
    [DllImport("KERNEL32.DLL", EntryPoint = "WritePrivateProfileStringW",
      SetLastError = true,
      CharSet = CharSet.Unicode, ExactSpelling = true,
      CallingConvention = CallingConvention.StdCall)]
    private static extern int WritePrivateProfileString(
      string lpSection,
      string lpKey,
      string lpValue,
      string lpFileName);
 
    private string _path = "";
    public string Path {
        get
        {
            return _path;
        }
        set
        {
            if (!File.Exists(value))
                File.WriteAllText(value, "", Encoding.Unicode);
            _path = value;
        }
    }
 
    /// <summary>
    /// INIFile Constructor.
    /// </summary>
    /// <PARAM name="INIPath"></PARAM>
    public IniFile(string INIPath)
    {
        this.Path = INIPath;
    }
 
    /// <summary>
    /// Write Data to the INI File
    /// </summary>
    /// <PARAM name="Section"></PARAM>
    /// Section name
    /// <PARAM name="Key"></PARAM>
    /// Key Name
    /// <PARAM name="Value"></PARAM>
    /// Value Name
    public void IniWriteValue(string Section, string Key, string Value)
    {
        WritePrivateProfileString(Section, Key, Value, this.Path);
    }
 
    /// <summary>
    /// Read Data Value From the Ini File
    /// </summary>
    /// <PARAM name="Section"></PARAM>
    /// <PARAM name="Key"></PARAM>
    /// <PARAM name="Path"></PARAM>
    /// <returns></returns>
    public string IniReadValue(string Section, string Key)
    {
        const int MAX_CHARS = 1023;
        StringBuilder result = new StringBuilder(MAX_CHARS);
        GetPrivateProfileString(Section, Key, "", result, MAX_CHARS, this.Path);
        return result.ToString();
    }
}

GeneralMy vote of 5memberkoiser13 Feb '12 - 3:51 
Clear structured an easy to use!
GeneralMy vote of 5membersanket_14@rediff.com1 Nov '11 - 20:40 
Thankx Dear...!!! It helps me lot...!!!
 
But i hav one query....if i want to use <> this for defining Section i.e.
 
how to read this test.ini file?
 

=
GeneralMy vote of 5memberAli Fakoor21 Oct '11 - 21:44 
very creative article
QuestionRead and write ini files in VB.NetmemberNasenbaaer5 Oct '11 - 3:46 
My piece of code in VB.Net
 
 <Runtime.InteropServices.DllImport("kernel32.dll", CharSet:=Runtime.InteropServices.CharSet.Ansi, SetLastError:=True)> _
            Private Function WritePrivateProfileString(Section As String, Key As String, Value As String, FilePath As String) As Long
            End Function
 
            <Runtime.InteropServices.DllImport("kernel32.dll", CharSet:=Runtime.InteropServices.CharSet.Ansi, SetLastError:=True)> _
            Private Function GetPrivateProfileString(Section As String, Key As String, DefaultValue As String, Result As System.Text.StringBuilder, Size As Integer, FilePath As String) As Long
            End Function
 

            ''' <summary>
            ''' Modify or create an value in an ini file. 
            ''' </summary>
            ''' <param name="FilePath">Path of ini file for example: C\Mydirectory\file.ini</param>
            ''' <param name="Section">Keyword Parent</param>
            ''' <param name="Key">Keyword</param>
            ''' <param name="Value">Value to store</param>
            ''' <returns>True if successfully</returns>
            ''' <remarks>Timo Böhme, www.goldengel.ch, info@goldengel.ch, http://msdn.microsoft.com/en-us/library/windows/desktop/ms724353%28v=vs.85%29.aspx
            ''' IniFileModifyValue:
            ''' If the function successfully copies the string to the initialization file, the return value is nonzero.</remarks>
            Public Function IniFileModifyValue(ByVal FilePath As String, ByVal Section As String, ByVal Key As String, ByVal Value As String) As Boolean
                Dim ret As Long
                Try
                    ret = WritePrivateProfileString(Section, Key, Value, FilePath)
                    If ret = 0 Then Return False
                Catch ex As Exception
                    Return False
                End Try
                Return True
            End Function
 

            ''' <summary>
            ''' Read an existing value in an ini file. Returns the default value if file or key does not exist.
            ''' </summary>
            ''' <param name="FilePath">Path of ini file for example: C\Mydirectory\file.ini</param>
            ''' <param name="Section">Keyword Parent</param>
            ''' <param name="Key">Keyword</param>
            ''' <param name="DefaultValue">Value to store</param>
            ''' <returns>The value from ini file</returns>
            ''' <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/ms724353%28v=vs.85%29.aspx
            ''' GetPrivateProfileString 
            ''' The return value is the number of characters copied to the buffer, not including the terminating null character.</remarks>
            Public Function IniFileReadSingleValue(FilePath As String, Section As String, Key As String, DefaultValue As String) As String
                Dim ret As Long
                Dim res As String = DefaultValue
                Dim sb As New System.Text.StringBuilder(255)
                If IO.File.Exists(FilePath) = True Then
 

                    ret = GetPrivateProfileString(Section, Key, DefaultValue, sb, sb.Capacity, FilePath)
                    If ret > 0 Then
                        ret = Global.System.Math.Min(ret, sb.Capacity) 'important! because ret could be more than 255
                        ret = Global.System.Math.Min(ret, sb.Length) 'important! because buffer can be unused and less than 255
                        res = sb.ToString(0, ret)
                    End If
                End If
 
                Return res
            End Function

GeneralMy vote of 5memberNasenbaaer5 Oct '11 - 3:45 
Thanks
Questionhave 5 starsmemberShivamkalra22 Jun '11 - 18:57 
It solved my problem and useful article..
Question5 starmemberShivamkalra22 Jun '11 - 18:56 
It solved my problem and useful article..
RantOKmembermebaba12 May '11 - 23:06 
this Cod is perfect .. Thx a lot Smile | :) Smile | :)
GeneralMy vote of 5memberMember 4458079 Jose5 May '11 - 15:35 
Nice job. Thank you.
GeneralMy vote of 5memberdv7617 Mar '11 - 22:20 
Great article
Generalsuggestion to add some more methods to this class.memberhugoandrioli@yahoo.com28 Dec '10 - 0:15 
///
/// see IniWriteValue, but write an integer
///

public void IniWriteInt(string section, string key, int value)
{

String s = Convert.ToString(value);
IniWriteValue(section, key, s);
}
 
///
/// see IniReadValue, but read as an integer.
///

public int IniReadInt(string section, string key)
{
String s= IniReadValue(section,key);
String exceptionMsg = "string could not be converted to an int";
int value;
try
{
value = Convert.ToInt32(s);
}
catch (FormatException ex)
{
throw new IniFileException(exceptionMsg, ex);
}
catch (OverflowException ex)
{
throw new IniFileException(exceptionMsg, ex);
}
return value;
}
 

public class IniFileException : Exception
{
//TODO put this class in it's own file.
 

public IniFileException(String message)
: base(message)
{
}
 
public IniFileException(string message, Exception ex)
: base(message, ex)
{
}
}
GeneralRe: suggestion to add some more methods to this class.membermd5sum5 Jan '11 - 9:28 
This is way overcomplicated. Try this instead:
public class IniFile
{
    public string path;
 
    [DllImport("kernel32")]
    private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
 
    [DllImport("kernel32")]
    private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
 
    public IniFile(string INIPath)
    {
        path = INIPath;
    }
 
    public void IniWriteValue(string Section, string Key, string Value)
    {
        WritePrivateProfileString(Section, Key, Value, this.path);
    }
 
    public string IniReadValue(string Section,string Key, string Def)
    {
        StringBuilder temp = new StringBuilder(255);
        int i = GetPrivateProfileString(Section, Key, (def != null ? def : string.Empty), temp, 255, this.path);
        return temp.ToString();
    }
 
    public void IniWriteValue(string Section, string Key, int Value)
    {
        IniWriteValue(Section, Key, Value.ToString());
    }
 
    public int IniReadValue(string section, string key, int? def)
    {
        string s = ReadValue(section, key, (def != null ? def.ToString() : null));
        int i = 0;
        if (int.TryParse(s, out i))
            return i;
        else
            throw new IniFileException("Tried to retrieve invalid value type from ini.");
    }
}
 
public class IniFileException : Exception
{
    public IniFileException(string Message)
        : base(Message)
    {
 
    }
}
 
Your stack trace will now have everything you need, and you can get rid of the messy try...catch...throw. There's no need to include an InnerException as part of the newly thrown IniFileException, as no other Exception has been generated yet.
 
You have room for a default value now, and you're using overloads instead of multiple alternately named, similar functions. This is a more standardized method for this sort of endeavor.
 
An int.TryParse is just a hair slower than a Convert.ToInt32 but the overhead this method will save you on failure is well worth it. Additionally, it's the preferred method for conversion.
GeneralRe: suggestion to add some more methods to this class.member(^-^)h~ugo5 Jan '11 - 11:45 
Hi md5sum, thx for your insight here!
Allthough the methodes I posted
do what they supposed to, I agree
with overloading, the methods you posted.
I made changes accordingly. However I am not sure
about using tryparse. if reading from ini would fail because
the number is too high to be parsed or there is an invalid
format, then you can't distinqush between those cases from
iniexception anymore.
GeneralRe: suggestion to add some more methods to this class. [modified]membermd5sum5 Jan '11 - 12:02 
I suppose if you need that much granularity in your error reporting, then it would be necessary to report it that way. However, I would probably instead change:
throw new IniFileException("Tried to retrieve invalid value type from ini.");
to:
throw new IniFileException(string.Format("Tried to retrieve invalid value type from ini. Tried to convert \"{0}\" to int.", s));
in order to introduce the same level of reporting the cause of the error without the granularity of exception types generated through the alternate, multiple catch method. I can't imagine an instance where I would need (for myself or my users) to have more than a single exception generated from this block of code. In general though, if you absolutely want to keep the InnerException and specifically NOT use a TryParse, I would limit it to simply:
try
{
    i = Convert.ToInt32(s);
}
catch (Exception ex)
{
    throw new IniFileException("Tried to retrieve invalid value type from ini.", ex);
}
and add the following constructor back to the IniFileException class:
public IniFileException(string Message, Exception ex)
    : base(Message, ex)
{
 
}
 
This will keep your granularity in exception types, rethrowing the wrapped exception with an appropriate InnerException. I just can't imagine why you would want that in this particular case.
modified on Friday, January 7, 2011 2:38 PM

GeneralRe: suggestion to add some more methods to this class.membertttony076 Mar '11 - 15:48 
good class Thumbs Up | :thumbsup:
 
but where is the ReadValue() method??
 
EDIT:
 
is IniReadValue()
 
Thanks for the code!!
GeneralStrings longer than 254 characters will be truncated.memberdgph21 Nov '10 - 17:34 
The code will only be able to retrieve strings that are 254 characters or less (to fit in a null-terminated buffer of 255 characters), otherwise they will be truncated.
int i = GetPrivateProfileString(Section,Key,"",temp, 255, this.path);

GeneralRe: Strings longer than 254 characters will be truncated.memberf.rivato16 Jan '13 - 21:35 
Found the same problem. May be the author should easy fix this bug?
GeneralMy vote of 3memberDaniel Moreland4 Nov '10 - 12:10 
don't explain exactly where tu put the items. nice help, but to those who has some knoledge in C# already

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 15 Mar 2002
Article Copyright 2002 by BLaZiNiX
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid