Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / MFC
Article

XML Application Profile Class

Rate me:
Please Sign up or sign in to vote.
4.60/5 (23 votes)
27 Jan 2007CPOL5 min read 71.4K   755   45   18
Implement XML application profiles that are similar (but not too similar) to using INI files

Introduction

I hate putting stuff in the registry. It's not portable, it just adds bulk that's only needed by my application, and it's problematic to backup in case you want to move the app to another machine or easily recover from a reformat/reinstall of Windows. However, every time I mention "put it in an INI file", all of the zealots here on CP complain the INI files are obsolete, and we should always use the registry. Yeah, right, blah blah blah.

I will however admit that INI files are limited in their functionality in a number of ways. They can't be bigger than 64k in size, and data items can be no longer than 256 characters. They can also be difficult to use if you want to do anything more than simply setting/getting data from them. Finally, Microsoft could, at any time, remove the API functions that support them. These are the primary reasons that I wrote the CProfile class.

The CProfile class

This class reads XML files that are formatted in a style similar to INI files. In other words, give the following INI file contents:

[GENERAL]
setting1=0
setting2=test
[SPECIAL]
setting1=spider
setting2=0.12345

... the XML version supported by CProfile would look like this:

XML
<xml>
    <GENERAL>
        <setting1>0</setting1>
        <setting2>test</setting2>
    </GENERAL>
    <SPECIAL>
        <setting1>spider</setting1>
        <setting2>0.12345</setting2>
    </SPECIAL>
</xml>

Since the class is simply trying to emulate the functionality of INI files, all top-level nodes are considered to be evquivalant to INI sections, and each "section" contains one or more child nodes (the same thig as INI "keys"). Child nodes under the keys are ignored - remember, we're just emulating INI files, not an all-encompassing XML file reader. I kept this within the context of an INI file because that's all I need. If you want to make this all-encompassing, have at it, but don't ask me to do it for you. You're a programmer - make it fit your needs.

Inner Workings

CProfile maintains a CTypedPtrArray of profile items. Each profile item contains three CStrings - its section, its key name, and its value. Converting to and from the desired intrinsic type is handled in a series of overloaded Set/Get functions.

The class uses MSXML.DLL and imports the typelib. This way, I don't have to worry about any weird (and often unreliable) XML parsing classes that may only partially implement what's needed to properly parse a XML file. The only thing you have to remember to do is to call CoInitialize() before you call the CProfile::Load() function (and remember to call CoUninitialize() before exiting your app). I just stick a call to CoInitialize() at the top of my InitInstance() function, and CoUninitialize() in my ExitInstance() function - nice and tidy.

Using CProfile

Using CProfile is a simple matter of creating a variable somewhere in your application like so:

#include "Profile.h"

CProfile m_profile;

...and then loading the file:

m_profile.Load("");

When you call CProfile::Load(), you need to supply string that represents a file name. If the filename is blank or is not a complete path/filename, the class will attempt to "normalize" the filename in the following ways:

  • If the filename is empty, the class assumes that it's supposed to be myapp.xml and located in the same folder as the executable.
  • If the filename is just a path, the class assumes that it's supposed to be myapp.xml and verifies that the path you specified exists. If it doesn't exist, it sets the path to the path of the executable file.
  • If the filename is a path with just an extension, the class will set the filename to the app's name.

In the end, an acceptable filename should always be the result. The file does not have to exist, but the path must.

After the profile is loaded, you can access the data. If you attempt to retrieve a value whose section/key does not yet exist, that section/key/value is added to the list of values maintained within CProfile. If you try to set a section/key/value that doesn't exist, it will be automatically created and added to the list.

By default, CProfile will automatically save its data when it goes out of scope. If you don't want this functionality, simply include this line anytime within the current scope.

CProfile::SetAutoSave(false);

The class will not save until either you explicitly call the Save() function, or the CProfile object goes out of scope (and auto-save is turned on).

Getting and Setting Values

By default, if you try to get or set a value for a key that doesn't exist, CProfile will automatically create the key in the list. This duplicates the functionality of the Get/SetPrivateProfileString API for INI files. However, you can turn that functionality on and off for sets, gets, or both by calling the appropriate toggle function:

CProfile::SetAddOnFailedGets(bool)
CProfile::SetAddOnFailedSets(bool)

The default value is true for both toggles.

Debugging Functionality

If you want to make sure that your xml file loaded as expected, there are two built-in functions in CProfile that show the contents of the internal list - ShowContentsByRange() and ShowContentsBySection().

The "ByRange" function allows you to view all of the items within the specified index range. If you don't pass any range info at all, it assumes you want to see all of the items. Normally this shouldn't be a problem, but just in case you have a billion keys, you can specify a smaller range of items to view.

The "BySection" function shows all keys for the specified section. Again, this shouldn't normally be a problem, but if you have over 25 keys in a given section, you should consider writing an overload of this function that also accepts a non-optional set of range parameters.

Extra Stuff

I've also included some code that supports filename manipulation. It is provided only to support CProfile and discussion of that code is not within the context of this article. Feel free to talk amongst yourselves, but I won't be fielding any questions about it.

Disclaimers and Warranties

So there it is - nothing fancy and definitely not hard to use or understand. I'm sure there's something in this code that someone won't like, so instead of complaining about it, be a programmer and change it to suit your needs. Good luck.

License

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


Written By
Software Developer (Senior) Paddedwall Software
United States United States
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.

My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Comments and Discussions

 
GeneralCan't compile on VS2008 on Windows 7 Pin
Super Garrison11-May-11 5:57
Super Garrison11-May-11 5:57 
QuestionPerformance ? Pin
Defenestration1-Nov-07 12:51
Defenestration1-Nov-07 12:51 
AnswerRe: Performance ? Pin
#realJSOP1-Nov-07 23:39
mve#realJSOP1-Nov-07 23:39 
GeneralAnother Reason to be Portable Pin
hstahl24-Jun-07 5:42
hstahl24-Jun-07 5:42 
QuestionVista UAC: What's the Future For XML-style (and ini-style) Initialization? Pin
Mike O'Neill15-Feb-07 7:23
Mike O'Neill15-Feb-07 7:23 
AnswerRe: Vista UAC: What's the Future For XML-style (and ini-style) Initialization? Pin
#realJSOP15-Feb-07 23:46
mve#realJSOP15-Feb-07 23:46 
GeneralRe: Vista UAC: What's the Future For XML-style (and ini-style) Initialization? Pin
Mike O'Neill16-Feb-07 7:58
Mike O'Neill16-Feb-07 7:58 
AnswerRe: Vista UAC: What's the Future For XML-style (and ini-style) Initialization? Pin
#realJSOP15-Feb-07 23:52
mve#realJSOP15-Feb-07 23:52 
AnswerRe: Vista UAC: What's the Future For XML-style (and ini-style) Initialization? Pin
Drew Stainton16-Feb-07 5:53
Drew Stainton16-Feb-07 5:53 
AnswerRe: Vista UAC: What's the Future For XML-style (and ini-style) Initialization? Pin
John Crenshaw20-Apr-07 11:43
John Crenshaw20-Apr-07 11:43 
QuestionWhy not use xml attributes? Pin
Shao Voon Wong6-Feb-07 14:34
mvaShao Voon Wong6-Feb-07 14:34 
AnswerRe: Why not use xml attributes? Pin
#realJSOP6-Feb-07 23:10
mve#realJSOP6-Feb-07 23:10 
GeneralReally Nice Pin
Rama Krishna Vavilala27-Jan-07 14:28
Rama Krishna Vavilala27-Jan-07 14:28 
QuestionXML now? Pin
Jörgen Sigvardsson27-Jan-07 5:25
Jörgen Sigvardsson27-Jan-07 5:25 
AnswerRe: XML now? Pin
#realJSOP27-Jan-07 5:46
mve#realJSOP27-Jan-07 5:46 
GeneralRe: XML now? Pin
Jörgen Sigvardsson27-Jan-07 6:59
Jörgen Sigvardsson27-Jan-07 6:59 
GeneralRe: XML now? Pin
#realJSOP27-Jan-07 7:31
mve#realJSOP27-Jan-07 7:31 
GeneralRe: XML now? Pin
Mike_V27-Jan-07 9:30
Mike_V27-Jan-07 9:30 

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.