INI Reader / Writer Class for C#, VB.NET, and VBScript






4.78/5 (53 votes)
Read and write to INI files in VB.NET and VBScript
- Download Visual Studio 2019 Project - 33 KB
- Download VB.NET and C# Source - 7.1 KB
- Download Inifile VBScript Source - 4.1 KB
Introduction
Originally, this started out as a C++ class (CIniFile) in 2005. Since then, I rewrote CIniFile
so it would be more efficient. The following code is a C#\VB.NET\VBScript port of the C++ code. Almost all the class names are the same. with the exception to the leading "C" which has been dropped. The current class names are IniFile
, IniSection
, and IniKey
.
To help with understanding how to use the code, usage in the following languages will be demonstrated:
- C#
- VB.NET
- VBScript
The following source versions of the Inifile
object are provided:
- C# - InifileCs.cs
- VB.NET - InifileVb.vb
- VBScript - IniFile.vbs
Efficiency
During testing on Windows7 running on a Lenovo T60 w\2GB RAM, IniFile
could generate an ini file holding 10000 sections with 100 keys per section and write it to disk in ~2 second(s). After increasing the keys per section to 1000, the file was generated in ~6 seconds. The file was 10,000,000 lines long, and was roughly 140MB in size. Reading the data back from the file into memory was in the same ball park.
[Section0]
Key0=KeyValue
Key1=KeyValue
Key2=KeyValue
...
[Section1]
Key0=KeyValue
Key1=KeyValue
Key2=KeyValue
...
Parsing and Behavior
Currently, IniFile
is designed to read most ini files. Ini sections should start with a "[" and end with a "]". Whitespace between "[" and "]" will be trimmed. For example, the section defined below would be interpreted as "SECTION
", not " SECTION
".
[ SECTION ]
...
...
...
Ini key\value pairs should have a key value separated by an "=" to the right of the key value. Key values are also trimmed to remove whitespace. For example, the key defined below would be interpreted as "MyKeyValue=SomeData
". The resulting key would be "MyKeyValue
" and value would be "SomeData
".
[ SECTION ]
MyKeyValue =SomeData
...
...
Ini key values, however, are not trimmed, and whitespace is preserved. For example, the key defined below would be interpreted as "MyIniKey= SomeDataWithSpaces
". The resulting key would be "MyKeyValue
", and value would be " SomeDataWithSpaces
".
[ SECTION ]
MyKeyValue = SomeDataWithSpaces
...
...
Functions and Returns
// IniFile class used to read and write
// ini files by loading the file into memory
public class IniFile
{
// Public constructor
public IniFile()
// Loads the Reads the data in the ini file into the IniFile object
public void Load(string sFileName )
// Loads the Reads the data in the ini file into the IniFile object
public void Load(string sFileName, bool bMerge )
// Used to save the data back to the file or your choice
public void Save(string sFileName)
// Gets all the sections names
public System.Collections.ICollection Sections
// Adds a section to the IniFile object,
// returns a IniSection object to the new or existing object
public IniSection AddSection(string sSection )
// Returns true on success, removes a section
// by its name sSection, returns trus on success
public bool RemoveSection(string sSection)
// Returns true on success, removes section by object, returns trus on success
public bool RemoveSection(IniSection Section)
// Returns true on success,
// removes all existing sections, returns trus on success
public bool RemoveAllSections()
// Returns an IniSection to the section by name, NULL if it was not found
public IniSection GetSection(string sSection)
// Returns a KeyValue in a certain section
public string GetKeyValue(string sSection, string sKey)
// Returns true on success, sets a KeyValuePair in a certain section
public bool SetKeyValue(string sSection, string sKey, string sValue)
// Renames an existing section returns true on success,
// false if the section didn't exist or there
// was another section with the same sNewSection
public bool RenameSection(string sSection, string sNewSection)
// Renames an existing key returns true on success,
// false if the key didn't exist or there
// was another section with the same sNewKey
public bool RenameKey(string sSection, string sKey, string sNewKey)
// IniSection class
public class IniSection
{
// Constuctor so objects are internally managed
protected internal IniSection(IniFile parent, string sSection)
// Returns and hashtable of keys associated with the section
public System.Collections.ICollection Keys
// Returns the section name
public string Name
// Adds a key to the IniSection object,
// returns a IniKey object to the new or existing object
public IniKey AddKey(string sKey)
// Returns true on success, removes a single key by string
public bool RemoveKey(string sKey)
// Returns true on success, removes a single key by IniKey object
public bool RemoveKey(IniKey Key)
// Returns true on success, Removes all the keys in the section
public bool RemoveAllKeys()
// Returns a IniKey object to the key by name, NULL if it was not found
public IniKey GetKey(string sKey)
// Sets the section name, returns true on success, fails if the section
// name sSection already exists
public bool SetName(string sSection)
// Returns the section name
public string GetName()
// IniKey class
public class IniKey
{
// Constuctor so objects are internally managed
protected internal IniKey(IniSection parent, string sKey)
// Returns the name of the Key
public string Name
// Sets or Gets the value of the key
public string Value
// Sets the value of the key
public void SetValue(string sValue)
// Returns the value of the Key
public string GetValue()
// Sets the key name
// Returns true on success,
// fails if the section name sKey already exists
public bool SetName(string sKey)
// Returns the name of the Key
public string GetName()
} // End of IniKey class
} // End of IniSection class
} // End of IniFile class
Using IniFile.Sections and IniSection.Keys
The following code will demonstrate how to use the Sections
and Keys
properties:
IniFile ini = new IniFile();
ini.Load("C:\\temp\\test.ini");
foreach (IniSection s in ini.Sections)
{
Trace.WriteLine(string.Format("Section: [{0}]", s.Name));
foreach (IniSection.IniKey k in s.Keys)
{
if (k.Value != string.Empty)
{
Trace.WriteLine(string.Format("Key: {0}={1}", k.Name, k.Value));
}
else
{
Trace.WriteLine(string.Format("Key: {0}", k.Name));
}
}
}
Merging INI files
The following code demonstrates merging two ini files:
IniFile ini = new IniFile();
// Load the first ini into the object
ini.Load("C:\\temp\\test1.ini");
// Load the second ini into the object
// (common section's keys will overwrite)
ini.Load("C:\\temp\\test2.ini" , true );
// Resulting combined ini
ini.Save("C:\\temp\\test1and2.ini" );
Using IniFile in C#
This code demonstrates the usage in C#:
static void Main(string[] args)
{
IniFile ini = new IniFile();
// Load and existing file
// ini.Load("C:\\temp\\ini2open.ini");
ini.AddSection("TEST_SECTION").AddKey("Key1").Value = "Value1";
ini.AddSection("TEST_SECTION").AddKey("Key2").Value = "Value2";
ini.AddSection("TEST_SECTION").AddKey("Key3").Value = "Value3";
ini.AddSection("TEST_SECTION").AddKey("Key4").Value = "Value4";
ini.AddSection("TEST_SECTION").AddKey("Key5").Value = "Value5";
ini.AddSection("TEST_SECTION").AddKey("Key6").Value = "Value6";
ini.AddSection("TEST_SECTION").AddKey("Key7").Value = "Value7";
ini.AddSection("TEST_SECTION_2").AddKey("Key1").Value = "Value1";
ini.AddSection("TEST_SECTION_2").AddKey("Key2").Value = "Value2";
ini.AddSection("TEST_SECTION_2").AddKey("Key3").Value = "Value3";
ini.AddSection("TEST_SECTION_2").AddKey("Key4").Value = "Value4";
ini.AddSection("TEST_SECTION_2").AddKey("Key5").Value = "Value5";
ini.AddSection("TEST_SECTION_2").AddKey("Key6").Value = "Value6";
ini.AddSection("TEST_SECTION_2").AddKey("Key7").Value = "Value7";
// Key Rename Test
Trace.Write("Key Rename Key1 -> KeyTemp Test: ");
if (ini.RenameKey("TEST_SECTION", "Key1", "KeyTemp"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Section Rename Test
Trace.Write("Test section rename TEST_SECTION -> TEST_SECTION_3: ");
if (ini.RenameSection("TEST_SECTION", "TEST_SECTION_3"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check Key Rename Post Section Rename
Trace.Write("Test TEST_SECTION_3 rename key KeyTemp -> Key1: ");
if (ini.RenameKey("TEST_SECTION_3", "KeyTemp", "Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check Section Rename Post Section Rename
Trace.Write("Test section rename TEST_SECTION_3 -> TEST_SECTION: ");
if (ini.RenameSection("TEST_SECTION_3", "TEST_SECTION"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check Key Rename Key1 -> Key2 where Key2 exists
Trace.Write("Test TEST_SECTION key rename Key1 -> Key2 where Key2 exists: ");
if (ini.RenameKey("TEST_SECTION", "Key2", "Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check Key Rename
Trace.Write("Test TEST_SECTION key rename Key2 -> Key2Renamed: ");
if (ini.RenameKey("TEST_SECTION", "Key2", "Key2Renamed"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Test rename other section
Trace.Write("Test section rename TEST_SECTION_2 -> TEST_SECTION_1 : ");
if (ini.RenameSection("TEST_SECTION_2", "TEST_SECTION_1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check remove key
Trace.Write("Test TEST_SECTION_1 remove key Key1: ");
if (ini.GetSection("TEST_SECTION_1").RemoveKey("Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check remove key no exist
Trace.Write("Test TEST_SECTION_1 remove key Key1: ");
if (ini.GetSection("TEST_SECTION_1").RemoveKey("Key1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check remove section
Trace.Write("Test remove section TEST_SECTION_1: ");
if (ini.RemoveSection("TEST_SECTION_1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
// Check remove section no exist
Trace.Write("Test remove section TEST_SECTION_1: ");
if (ini.RemoveSection("TEST_SECTION_1"))
Trace.WriteLine("Pass");
else
Trace.WriteLine("Fail");
//Save the INI
ini.Save("C:\\temp\\test.ini");
}
Using IniFile in VB.NET
This code demonstrates the usage in VB.NET:
Sub Main()
Dim ini As New IniFile
' Load and existing file
' ini.Load("C:\temp\ini2open.ini")
ini.AddSection("TEST_SECTION").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION").AddKey("Key7").Value = "Value7"
ini.AddSection("TEST_SECTION_2").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION_2").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION_2").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION_2").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION_2").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION_2").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION_2").AddKey("Key7").Value = "Value7"
' Key Rename Test
Trace.Write("Key Rename Key1 -> KeyTemp Test: ")
If ini.RenameKey("TEST_SECTION", "Key1", "KeyTemp") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Section Rename Test
Trace.Write("Test section rename TEST_SECTION -> TEST_SECTION_3: ")
If ini.RenameSection("TEST_SECTION", "TEST_SECTION_3") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check Key Rename Post Section Rename
Trace.Write("Test TEST_SECTION_3 rename key KeyTemp -> Key1: ")
If ini.RenameKey("TEST_SECTION_3", "KeyTemp", "Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check Section Rename Post Section Rename
Trace.Write("Test section rename TEST_SECTION_3 -> TEST_SECTION: ")
If ini.RenameSection("TEST_SECTION_3", "TEST_SECTION") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check Key Rename Key1 -> Key2 where Key2 exists
Trace.Write("Test TEST_SECTION key rename Key1 -> Key2 where Key2 exists: ")
If ini.RenameKey("TEST_SECTION", "Key2", "Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check Key Rename
Trace.Write("Test TEST_SECTION key rename Key2 -> Key2Renamed: ")
If ini.RenameKey("TEST_SECTION", "Key2", "Key2Renamed") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Test rename other section
Trace.Write("Test section rename TEST_SECTION_2 -> TEST_SECTION_1 : ")
If ini.RenameSection("TEST_SECTION_2", "TEST_SECTION_1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check remove key
Trace.Write("Test TEST_SECTION_1 remove key Key1: ")
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check remove key no exist
Trace.Write("Test TEST_SECTION_1 remove key Key1: ")
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check remove section
Trace.Write("Test remove section TEST_SECTION_1: ")
If ini.RemoveSection("TEST_SECTION_1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
' Check remove section no exist
Trace.Write("Test remove section TEST_SECTION_1: ")
If ini.RemoveSection("TEST_SECTION_1") Then
Trace.WriteLine("Pass") Else Trace.WriteLine("Fail")
'Save the INI
ini.Save("C:\temp\test.ini")
End Sub
Using IniFile in VBScript
This code demonstrates the usage in VBScript:
Option Explicit
Call Main
Sub Main()
Dim ini
Set ini = New IniFile
' Load and existing file
'ini.Load("C:\temp\ini2open.ini", false)
ini.AddSection("TEST_SECTION").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION").AddKey("Key7").Value = "Value7"
ini.AddSection("TEST_SECTION_2").AddKey("Key1").Value = "Value1"
ini.AddSection("TEST_SECTION_2").AddKey("Key2").Value = "Value2"
ini.AddSection("TEST_SECTION_2").AddKey("Key3").Value = "Value3"
ini.AddSection("TEST_SECTION_2").AddKey("Key4").Value = "Value4"
ini.AddSection("TEST_SECTION_2").AddKey("Key5").Value = "Value5"
ini.AddSection("TEST_SECTION_2").AddKey("Key6").Value = "Value6"
ini.AddSection("TEST_SECTION_2").AddKey("Key7").Value = "Value7"
' Key Rename Test
If ini.RenameKey("TEST_SECTION","Key1","KeyTemp") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Section Rename Test
If ini.RenameSection("TEST_SECTION","TEST_SECTION_3") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Check Key Rename Post Section Rename
If ini.RenameKey("TEST_SECTION_3","KeyTemp","Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Check Section Rename Post Section Rename
If ini.RenameSection("TEST_SECTION_3","TEST_SECTION") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Check Fail on Conflict
If ini.RenameKey("TEST_SECTION","Key2","Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Check Fail on Conflict
If ini.RenameKey("TEST_SECTION","Key2","Key2Renamed") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Test rename other section
If ini.RenameSection("TEST_SECTION_2","TEST_SECTION_1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Check remove key and conflict
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.GetSection("TEST_SECTION_1").RemoveKey("Key1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
' Check remove section and conflict
If ini.RemoveSection("TEST_SECTION_1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
If ini.RemoveSection("TEST_SECTION_1") Then
WScript.Echo "Pass" Else WScript.Echo "Fail"
'Save the INI
ini.Save("C:\temp\test.ini")
End Sub
Using the lib in .NET
In order to use the IniFile
library, it is necessary to add a reference to IniFile.dll.
History
- 12\14\2007 - Created - Initial VBScript version
- 12\08\2007 - Bug fixed - Regex parse string issue
- 08\23\2010 - Created - C# version which uses hashing
- 08\23\2010 - Created - VB.NET version which uses hashing
- 08\23\2010 - Created - VBScript version which uses hashing
- 11\12\2010 - Bug fixed - Section regex matching on key values with brackets
- 06\20\2015 - Bug fixed - Key parsing regex to account for keys with spaces in names
- 11\13\2015 - Bug fixed - Key parsing regex to account for keys with multiple equals
- 05\06\2021 - Bug fixed- Section regex to read everything within brakets and trim (single char issue)