Click here to Skip to main content
15,891,513 members
Articles / Programming Languages / C#
Article

An INI file enumerator class using C#

Rate me:
Please Sign up or sign in to vote.
3.67/5 (7 votes)
8 Dec 2008CPOL1 min read 68.6K   1.1K   32   11
An INI file enumerator class using C#.

Introduction

I found several snippets of code on the internet that uses the function GetPrivateProfileString from KERNEL32.DLL, but none of them offered the functionality I required. So, I created a C# class, INI, which exposes this function, utilizing the best elements from these snippets of code.

First, create a new C# Console Application. Then, add a new C# class. I called mine ReadINI.cs. Now, copy and paste the first section of code into this new class. Then, copy the second section of code into the C# Main Console Application class. Now, create a basic INI file on the root of C:\, called Test.ini.

[TestSectionHeader1]
TestKey11 = TestValue11
TestKey12 = TestValue12
TestKey13 = TestValue13
TestKey14 = TestValue14
TestKey15 = TestValue15

[TestSectionHeader2]
TestKey21 = TestValue21
TestKey22 = TestValue22
TestKey23 = TestValue23
TestKey24 = TestValue24
TestKey25 = TestValue25

[TestSectionHeader3]
TestKey31 = TestValue31
TestKey32 = TestValue32
TestKey33 = TestValue33
TestKey34 = TestValue34
TestKey35 = TestValue35

The Class

C#
using System;
using System.Text;
using System.Runtime.InteropServices;


namespace INI
{
    // Set the IniFileName class within the INI Namespace.
    public class IniFileName
    {
        //    Imports the Win32 Function "GetPrivateProfileString"
        ///   from the "Kernel32" class.
        //    I use 3 methods to gather the information. All have the same name
        //    as defind by the Win32 Function "GetPrivateProfileString"
        //
        //    First Method, Gathers the Value, as the SectionHeader and EntryKey are know.
        //
        //    Second Method, Gathers a list of EntryKey for the known SectionHeader 
        //
        //    Third Method, Gathers a list of SectionHeaders.
        

        // First Method
        [DllImport ("kernel32")]
        static extern int GetPrivateProfileString (string Section, string Key, 
               string Value, StringBuilder Result, int Size, string FileName);

        // Second Method
        [DllImport ("kernel32")]
        static extern int GetPrivateProfileString (string Section, int Key, 
               string Value, [MarshalAs (UnmanagedType.LPArray)] byte[] Result, 
               int Size, string FileName);

        // Third Method
        [DllImport ("kernel32")]
        static extern int GetPrivateProfileString (int Section, string Key, 
               string Value, [MarshalAs (UnmanagedType.LPArray)] byte[] Result, 
               int Size, string FileName);

        // Set the IniFileName passed from the Main Application.
        public string path;
        public IniFileName(string INIPath)
        {
            path = INIPath;
        }

        // The Function called to obtain the SectionHeaders,
        // and returns them in an Dynamic Array.
        public string[] GetSectionNames()
        {
            //    Sets the maxsize buffer to 500, if the more
            //    is required then doubles the size each time.
            for (int maxsize = 500; true; maxsize*=2)
            {
                //    Obtains the information in bytes and stores
                //    them in the maxsize buffer (Bytes array)
                byte[] bytes = new byte[maxsize];
                int size = GetPrivateProfileString(0,"","",bytes,maxsize,path);
                
                // Check the information obtained is not bigger
                // than the allocated maxsize buffer - 2 bytes.
                // if it is, then skip over the next section
                // so that the maxsize buffer can be doubled.
                if (size < maxsize -2)
                {
                    // Converts the bytes value into an ASCII char. This is one long string.
                    string Selected = Encoding.ASCII.GetString(bytes,0, 
                                               size - (size >0 ? 1:0));
                    // Splits the Long string into an array based on the "\0"
                    // or null (Newline) value and returns the value(s) in an array
                    return Selected.Split(new char[] {'\0'});
                }
            }
        }
        // The Function called to obtain the EntryKey's from the given
        // SectionHeader string passed and returns them in an Dynamic Array
        public string[] GetEntryNames(string section)
        {
            //    Sets the maxsize buffer to 500, if the more
            //    is required then doubles the size each time. 
            for (int maxsize = 500; true; maxsize*=2)
            {
                //    Obtains the EntryKey information in bytes
                //    and stores them in the maxsize buffer (Bytes array).
                //    Note that the SectionHeader value has been passed.
                byte[] bytes = new byte[maxsize];
                int size = GetPrivateProfileString(section,0,"",bytes,maxsize,path);

                // Check the information obtained is not bigger
                // than the allocated maxsize buffer - 2 bytes.
                // if it is, then skip over the next section
                // so that the maxsize buffer can be doubled.
                if (size < maxsize -2)
                {
                    // Converts the bytes value into an ASCII char.
                    // This is one long string.
                    string entries = Encoding.ASCII.GetString(bytes,0,
                                              size - (size >0 ? 1:0));
                    // Splits the Long string into an array based on the "\0"
                    // or null (Newline) value and returns the value(s) in an array
                    return entries.Split(new char[] {'\0'});
                }
            }
        }
        
        // The Function called to obtain the EntryKey Value from
        // the given SectionHeader and EntryKey string passed, then returned
        public object GetEntryValue(string section, string entry)
        {
            //    Sets the maxsize buffer to 250, if the more
            //    is required then doubles the size each time. 
            for (int maxsize = 250; true;maxsize *=2)
            {
                //    Obtains the EntryValue information and uses the StringBuilder
                //    Function to and stores them in the maxsize buffers (result).
                //    Note that the SectionHeader and EntryKey values has been passed.
                StringBuilder result = new StringBuilder(maxsize);
                int size = GetPrivateProfileString(section,entry,"", 
                                                   result, maxsize,path);
                if (size < maxsize -1)
                {
                    // Returns the value gathered from the EntryKey
                    return result.ToString();
                }
            }
        }
    }
}

Now, for the Main C# Console Application class.

I have included two routines for gathering information. The first is a foreach loop which is in the main body of the code. The second is commented out at the end of the code, and uses the IEnumerator function. Both produce the same results.

C#
using System;
using System.Collections;
// Set the system to using the INI Namespace within the ReadINI Class
using INI;


namespace MainApp
{
    //    Basic Console Application that will read a Common Windows INI file
    //    and display Enumerate Section Headers, Section Entries and Entries Values.
    
    class Class1
    {
                    
        // The main Console routine.
        [STAThread]
        static void Main(string[] args)
        {
            
            //    Sets the INI filename and location to be used.
            //    remember to use a double slash "\\"
            //    instead of a single for folder levels.
            IniFileName INI = new INI.IniFileName("C:\\test.ini");


            // Use the Try comman to gather the information,
            // if an error occurs then throw an exception.
            // and display the error.
            try 
            {
                // set the SectionHeader into an Dynamic Singlelevel Array.
                // the Information is gathered from the GetSectionNames
                // function INI namespace of the ReadINI Class.
                string [] SectionHeader = INI.GetSectionNames();
                                
                // Checks to see if the SectionHeader has returned null.
                if (SectionHeader != null)
                {
                // Returns a list EntryKey's for each of the SectionHeader(s).
                    foreach (string  SecHead in SectionHeader)
                    {
                        // Write the SectionHeader to the display.
                        Console.WriteLine(SecHead);
                                    
                        // Sets the Entry Dynamic Array for the each
                        // of the EntryKeys within the Section Header.
                        // If you already know the SectionHeader
                        // and just need to list the Entry's
                        // then enter the name instead of the SecHead
                        // in the GetEntrNames function.
                        // ie.  INI.GetEntryNames("TestSecHead")
                        string [] Entry = INI.GetEntryNames(SecHead);
                        // Checks to see if there's an Entry under
                        // the SectionHeader and the Entry has not returned a null
                        if (Entry != null)
                        {
                            // Enumerates a list of Keys For each of the Entry.
                            foreach (string EntName in Entry)
                            {
                                // writes to display the value for the Entry key.
                                // If you already know the SectionHeader
                                // and the Entry Key values then, replace all the code
                                // after the INIFileName line, with the following
                                // Console.WriteLine(" {0} = {1}", "TestKey", 
                                //         INI.GetEntryValue("TestSecHead","TestKey"));
                                // this will display the Value for the Entry key
                                // under the given SectionHeader.
                                Console.WriteLine(" {0} = {1}", EntName, 
                                                  INI.GetEntryValue(SecHead,EntName));
                            }
                        }
                
                    }
                }
            }
            // If an error if thrown, catch the exception error
            catch (Exception ex)
            {
                // Write the exception error to the display.
                Console.WriteLine("Error:  "+ ex);
            }
            // Waits for a "Enter" key to be used.
            // I use this like a pause button.
            Console.ReadLine();
        }
    }
}



/*    You can also use the Enumerator function to produce
 *    the same results. Here is the code if you wish to use that function.
 *    Replace the code from the "Try" at line 26 until
 *    the "console.readline()" at line 71 with this.
 * 
 *            try 
 *            {
 *                IEnumerator e = INI.GetSectionNames().GetEnumerator();
 *                while(e.MoveNext()) 
 *                {
 *                    string SectionHead = e.Current.ToString();
 *                    Console.WriteLine(e.Current);
 *                    IEnumerator d = INI.GetEntryNames(SectionHead).GetEnumerator();
 *                    while(d.MoveNext()) 
 *                    {
 *                        string EntryKey = d.Current.ToString();
 *                        Console.WriteLine("{0} = {1}", 
 *                           d.Current,INI.GetEntryValue(SectionHead,EntryKey));
 *                    }
 *
 *                }
 *            }
 *            catch (Exception ex)
 *            {
 *                Console.WriteLine( "Exception Error:  {0}", ex);
 *            }
 *            Console.ReadLine();
 * 
 * 
 *  
 * 
 */

And, that's it. Run the application to display your results.

Points of interest

I have also included the code in zip format for you. I hope this is of help to someone. This is my first posting, so please be gentle.. Can I also take this opportunity to thank all those other C# Guru's for their code snippets that helped me complete mine?

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionObservations on First Use: A Quirk, Probably of the Underlying API Pin
David A. Gray6-Sep-12 12:26
David A. Gray6-Sep-12 12:26 
GeneralMy vote of 5 Pin
bxyzst21-Mar-11 11:18
bxyzst21-Mar-11 11:18 
GeneralThe Reply Pin
Hilly_Billy22-Dec-08 0:32
Hilly_Billy22-Dec-08 0:32 
QuestionWhy use old Win32 functions when everything is built-in in a better way in .NET? Pin
Jacques Bourgeois16-Dec-08 16:31
Jacques Bourgeois16-Dec-08 16:31 
AnswerRe: Why use old Win32 functions when everything is built-in in a better way in .NET? Pin
E. del Ayre5-Jan-09 14:40
E. del Ayre5-Jan-09 14:40 
AnswerRe: Why use old Win32 functions when everything is built-in in a better way in .NET? Pin
Dave Rock 24-Jan-12 5:54
Dave Rock 24-Jan-12 5:54 
GeneralRe: Why use old Win32 functions when everything is built-in in a better way in .NET? Pin
David A. Gray6-Sep-12 11:49
David A. Gray6-Sep-12 11:49 
QuestionA suggestion? Pin
Wendelius9-Dec-08 7:17
mentorWendelius9-Dec-08 7:17 
AnswerRe: A suggestion? Pin
Keith Vinson16-Dec-08 6:01
Keith Vinson16-Dec-08 6:01 
AnswerRe: A suggestion? Pin
TobiasP16-Dec-08 10:15
TobiasP16-Dec-08 10:15 
GeneralRe: A suggestion? Pin
David A. Gray6-Sep-12 12:05
David A. Gray6-Sep-12 12:05 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.