//
you're reading...
Programming Issues/Tips

Using GetPrivateProfileSection() in C#

1. Introduction.

1.1 Recently, someone from the MSDN forum asked for advise on obtaing all the key/value pairs contained inside an INI file section.

1.2 The natural answer is the GetPrivateProfileSection() API.

1.3 However, using this API is a little tricky and unnatural for managed langauges like C#. This is because it returns the various key/value pairs in the section as null-terminated strings contained inside a buffer with the last string ending with 2 null characters.

1.4 It is really meant for use in pointer-friendly languages like C/C++. Please refer to its documentation in MSDN for more details :

GetPrivateProfileSection()

1.5 Nevertheless it is still possible to use it in C# albeit it can be a little convoluted. I have provided a sample code below (written in C#) for the reader to try out.

2. Sample Code in C#.

2.1 Listed below is the sample code. Please refer to the self-explanatory comments provided along with the code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace CSConsoleCApp01
{
    class Program
    {
        [DllImport("Kernel32.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi)]
        private static extern UInt32 GetPrivateProfileSection
            (
                [In] [MarshalAs(UnmanagedType.LPStr)] string strSectionName,
                // Note that because the key/value pars are returned as null-terminated
                // strings with the last string followed by 2 null-characters, we cannot
                // use StringBuilder.
                [In] IntPtr pReturnedString,
                [In] UInt32 nSize,
                [In] [MarshalAs(UnmanagedType.LPStr)] string strFileName
            );

        private static string [] GetAllKeysInIniFileSection(string strSectionName, string strIniFileName)
        {
            // Allocate in unmanaged memory a buffer of suitable size.
            // I have specified here the max size of 32767 as documentated
            // in MSDN.
            IntPtr      pBuffer = Marshal.AllocHGlobal(32767);
            // Start with an array of 1 string only.
            // Will embellish as we go along.
            string []   strArray = new string[0];
            UInt32      uiNumCharCopied = 0;

            uiNumCharCopied = GetPrivateProfileSection(strSectionName, pBuffer, 32767, strIniFileName);

            // iStartAddress will point to the first character of the buffer,
            int iStartAddress = pBuffer.ToInt32();
            // iEndAddress will point to the last null char in the buffer.
            int iEndAddress = iStartAddress + (int)uiNumCharCopied;

            // Navigate through pBuffer.
            while (iStartAddress < iEndAddress)
            {
                // Determine the current size of the array.
                int iArrayCurrentSize = strArray.Length;
                // Increment the size of the string array by 1.
                Array.Resize(ref strArray, iArrayCurrentSize + 1);
                // Get the current string which starts at "iStartAddress".
                string strCurrent = Marshal.PtrToStringAnsi(new IntPtr(iStartAddress));
                // Insert "strCurrent" into the string array.
                strArray[iArrayCurrentSize] = strCurrent;
                // Make "iStartAddress" point to the next string.
                iStartAddress += (strCurrent.Length + 1);
            }

            Marshal.FreeHGlobal(pBuffer);
            pBuffer = IntPtr.Zero;

            return strArray;
        }

        static void Main(string[] args)
        {
            string [] strArray = GetAllKeysInIniFileSection("SomeSection", "SomeIniFile.ini");

            for (int i = 0; i < strArray.Length; i++)
            {
                Console.WriteLine("{0:S}", strArray[i]);
            }
        }
    }
}

2.2 Note that I have declared the second parameter to GetPrivateProfileSection() as of type IntPtr instead of a StringBuilder which is usually used for an API like GetPrivateProfileString().

2.3 This is because the StringBuilder class will receive all characters returned by the API up to the first terminating null character. Hence, if the section contained multiple key/value pairs, only the first one will be contained in the StringBuilder variable.

 

Advertisements

About Lim Bio Liong

I've been in software development for nearly 20 years specializing in C , COM and C#. It's truly an exicting time we live in, with so much resources at our disposal to gain and share knowledge. I hope my blog will serve a small part in this global knowledge sharing network. For many years now I've been deeply involved with C development work. However since circa 2010, my current work has required me to use more and more on C# with a particular focus on COM interop. I've also written several articles for CodeProject. However, in recent years I've concentrated my time more on helping others in the MSDN forums. Please feel free to leave a comment whenever you have any constructive criticism over any of my blog posts.

Discussion

4 thoughts on “Using GetPrivateProfileSection() in C#

  1. WOW just what I was searching for. Came here by
    searching for %spinfile-E:\Users\Administrator\Dropbox\GSA\Mega Keyword List.txt

    Posted by Neva | April 22, 2013, 3:31 am
  2. Excellent. Thanks so much for sharing. Very useful.

    Posted by Dave | November 8, 2013, 11:20 pm
  3. Excellent! Excellent! Excellent! It work flawlessly.

    This site will be my latest resource for C to C# code development.

    Thanks

    Posted by John | May 4, 2015, 9:22 pm
  4. Excellent! Thank you for posting this solution

    Posted by Steve | July 15, 2016, 7:31 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: