Sometimes you’ll find your self in a situation where you need to use outdated techniques in order to support outdated applications … That time you’ll recognize that .NET does not support INI Files anymore.
So let us take a time machine and write our own INI File access.
First of all you have to declare two methods which are necessary to access an INI File.
[DllImport("KERNEL32.DLL", EntryPoint = "GetPrivateProfileStringW",
SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern int GetPrivateProfileString(
string lpAppName,
string lpKeyName,
string lpDefault,
string 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 lpAppName,
string lpKeyName,
string lpString,
string lpFilename);
Now let us code a small example that reads a simple ini file.
/*
* Try to read the content of a simle INI file
*/
List<string> categories = GetCategories(iniFile);
foreach (string category in categories)
{
Console.WriteLine(category);
/*
* Get the keys
*/
List<string> keys = GetKeys(iniFile, category);
foreach (string key in keys)
{
/*
* Now output the content
*/
string content = GetIniFileString(iniFile, category, key, defaultValue);
Console.WriteLine(string.Concat(" ", key, "\t", content));
}
}
As you can see I used three new methods GetCategories, GetKeys and GetIniFileString. These new methods are not an integrated part of the .NET framework. So we have to implement them by our own.
The following method reads a list with all categories the Ini File contains. A category within the Ini File is tagged with brackets, like [ODBC] or [GLOBALS]. The API GetPriveProfileString fills an internal buffer separated by \ 0. In order to get a generic list we have to split that buffer with the token \ 0. The last 2 values can be cutted, because they are always empty.
private static List<string> GetCategories(string iniFile)
{
string returnString = new string(' ', 65536);
GetPrivateProfileString(null, null, null, returnString, 65536, iniFile);
List<string> result = new List<string>(returnString.Split('\ 0'));
result.RemoveRange(result.Count - 2, 2);
return result;
}
Using the same technique we can read the keys from a category.
private static List<string> GetKeys(string iniFile, string category)
{
string returnString = new string(' ', 32768);
GetPrivateProfileString(category, null, null, returnString, 32768, iniFile);
List<string> result = new List<string>(returnString.Split('\ 0'));
result.RemoveRange(result.Count-2,2);
return result;
}
Lat but not least we need to read the value of the key we found.
private static string GetIniFileString(string iniFile, string category, string key, string defaultValue)
{
string returnString = new string(' ', 1024);
GetPrivateProfileString(category, key, defaultValue, returnString, 1024, iniFile);
return returnString.Split('\ 0')[0];
}
That’s all – and uhh, before I forget. Here’s an example for writing values to an INI File. We can use the declared and imported API method itself, without writing a wrapper to use it.
WritePrivateProfileString("GLOBAL", "Stuff", "The content of that stuff", "MyIniFile.ini");
But be aware, if you do not specify a directory, the INI File resides always within the Windows Directory. Most times this will be C:\Windows\
So have a nice day
Cheers
Gerhard
You can download the example using the following link: How to access INI Files in C# .NET
November 16, 2006 at 11:51 pm
Is there a way to make your application work in .NET Framework 1.1. “List” declaration seems to be supported in with Generics namespace in .NET Framework 2.0, is that true? How can I make this code run in the 1.1 environment.
Thanks in advance!
November 17, 2006 at 7:36 am
NET Framework 1.1 does not know generics. That’s why you have to replace List with ArrayList. That should be all.
Cheers
Gerhard
December 18, 2006 at 2:26 pm
[...] Because of the high resonance about the article “How to access INI Files in C# .NET” I want to introduce a blog entry on how to store configuration data into INI Files. [...]
February 14, 2007 at 1:39 pm
I have a scenario where I have to write 2-3 keys but with different values in the same section.
How to write duplicate keys in the same section?
Thanks in Advance
February 15, 2007 at 7:47 am
Hi Ashish,
Duplicate keys are not valid within an INI File. You have to enumerate the keys and add a counter to it. E.g.
Param01 = xxx
Param02 = yyy
Cheers
Gerhard
May 3, 2007 at 1:36 am
It seems it’s not. Every time I run this example I only get the first element, it’s just like I cannot get beyond the first ”. I tried everything it came to my mind, but I cannot retrieve the rest, any suggestion?
September 26, 2007 at 10:02 am
For those who are still wondering why the only character taken by the GetKeys/GetCategories functions is ” : I don’t really know if this problem occurs using .Net 2.0 (I’m currently using .Net 1.0 framework) but a string cannot be used as an argument of GetPrivateProfileString (argument “lpReturnString”, the string to fill). Instead, you should use StringBuilder to get a single string but it will truncate the StringBuilder at the first null it finds. In order to get the list of keys, you can use a char[] and then pass this char[] to the constructor of a new string. Then, it’s the same way of using it (split it into a list of strings, etc …).
Here is an example :
Dllimport :
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string defaultValue, [In, Out] char[] actualValue, int size, string ini_path);
GetKeys method :
private static ArrayList GetKeys(string iniFile, string category)
{
string test = new string(‘ ‘, 65535);
char[] returnString = test.ToCharArray();
GetPrivateProfileString(category, null, null, returnString, 65536, iniFile);
string resultString = new string(returnString);
ArrayList result = new ArrayList(resultString.Split(”));
result.RemoveRange(result.Count-2,2);
return result;
}
(Actually I couldn’t make an implicit conversion of a string to a char[]… http://msdn2.microsoft.com/fr-fr/library/x9h8tsay(VS.80).aspx said that it’s possible though :/ )
June 6, 2008 at 9:11 am
Thank you very much for u r great help in creating .ini file.
i helped me alot in my project. Thank you very much. Especially entire class is very useful
February 11, 2009 at 3:08 am
I have a question about writing to the ini. what happens if the node does not exist? will it just create it?
does writing a key update/create ?
or just update?
February 11, 2009 at 9:03 am
Hi Rogelio,
the key will be created. Even the complete file will be created, if it does not exists.
- Gerhard
November 6, 2009 at 10:47 am
Thanks for this, very useful indeed. So much so that I’m going to blog about it myself and of course credit your post.
November 6, 2009 at 11:32 am
[...] style ini file. I was struggling to find the best way to go about doing this, until I came across this blog post by Gerhard Stephan. In it, he describes how to attach to the Windows KERNEL32.dll file and use the [...]