A Configuration File
A configuration file is simply XML. The elements are defined for you, and it's extendable so that you can add your own elements if the standard ones aren't meeting your needs. Here's an example:
<configuration> <appSettings> <add key="connstr" value="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\deptstore.mdb" /> </appSettings> </configuration>
The entire file is a <configuration> element. Within that is an <appSettings> element—other elements not shown here can be used to instruct the .NET Framework how to handle this assembly while it's running. For example, .NET Remoting is set up using configuration file elements. Within the <appSettings> element are as many <add> elements as you want, each adding a name-value pair. The name of the configuration setting in this example is connstr and the value is "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\deptstore.mdb"—a reasonable connection string value.
(Don't forget, XML is case sensitive everywhere. <add> and <Add> are not the same. Watch carefully for upper- and lower-case letters in elements and attributes alike.)
So, where do you put this information? If you're building an application called HelloWorld.exe, the configuration file is called HelloWorld.exe.config—it's always the name of the executable assembly with .config tacked on the end. It belongs in the same folder as the executable assembly. In a minute, I'll show you a neat trick related to that.
Getting the Value from the File
If your configuration file was just any old file of XML, with a name like KatesImportantSettings.xml, what would you have to do to extract the setting from it? Find the file, open it, parse the XML, find the <add> element with a key attribute of "connstr", and then grab the value attribute from that element. The classes in the System.Xml namespace will make that reasonably simple, but you don't even need to do that much work.
Here's all you need to do:
ConnStr = Configuration::ConfigurationSettings:: AppSettings->get_Item("connstr");
One line of code! The framework takes care of everything for you: reading the config file when the application starts running, and filling in the name-value pairs into an AppSettings property of the ConfigurationSettings class. All you need to do is get the item.
Adding a Configuration File to the Project
At this point, you can just start using a config file in your next application. But, there's one small frustration. The config file must be in the same folder as the executable: If you're building a debug version, it's almost certainly in the Debug folder under your project folder, and if you're building a release version, it's almost certainly in a folder called Release. So, you would have to maintain two copies of the file, one in each folder. A better approach is to have a single config file in your project folder, and to copy that file to the Debug or Release folder whenever you build the application.
You could call the file anything you want, but you might as well hook into a mechanism that takes care of this automatically in VB and C#. In Solution Explorer, right-click your project and choose Add, Add New Item. Find the Configuration File choice and notice that you can't choose the name—it will be called app.config for you, and created with the enclosing <configuration> element already in place. You then can put your <appSettings> element in and add <add> elements with name-value pairs.
If you were working in VB or C#, you'd be done, but the C++ build process doesn't automatically copy the file for you. No problem; we C++ developers have been setting up our own build steps forever. Right-click the project again and choose Properties. Under the Configuration Properties folder is a list of folders including the Build Events folder; select that one. Inside that folder, select the Post Build Event entry.
What you want here is to enter a command in the Command Line setting. For a debug build of an application called HelloWorld.exe, it should read like this:
copy app.config Debug\HelloWorld.exe.config
Now, you could just type this string in, then flip the Configurations dropdown at the top left to Release and type a similar string, but I prefer to use some macros to make this generic—it won't even need to be edited if I change the name of the application. First, change the Configurations dropdown to AllConfigurations, then enter this command line:
copy app.config "$(TargetPath).config"
You can get a little help with this: First, type "copy app.config" followed by a space and a double quote into the CommandLine settings, then click the ... button. On the dialog that appears, click the Macros button. Look at all the file names and paths that you see there: These are very useful, and you can see that TargetPath corresponds to the full path to your executable. When you're building a debug version, it goes to the debug folder; release goes to release.
Make sure the cursor is at the end of your partially-typed line, then double-click TargetPath in the list at the bottom of the dialog. Then type a closing double quote followed by ".config" at the end of the line and click OK. Click OK on the Properties dialog and your custom-built step is in place. (You need the double quotes if there are spaces in your full path, and there are plenty in a path like C:\Documents and Settings\yourname\My Documents\Visual Studio Projects, which is quite likely the folder where your projects are created.)
Because it's a post-build step, it happens only after a successful build. If you have compile or link errors, the post-build steps don't happen. And, if you ever edit app.config without changing any code, you need to build the project to trigger your copy, even though the code doesn't need to be compiled. You might need to do a Rebuild if your code is up to date.
Now, every time your project builds, your app.config file will be copied to the appropriately named config file in the right folder.
What Kinds of Applications Can Have a Configuration File?
The most obvious use of configuration files is in Windows applications, assemblies that end with .exe. You can also use them in console applications and Windows Services. The configuration file must be in the same folder as the executable. ASP.NET applications, which are hardly ever written in C++, have config files called web.config. (Using the same name across applications makes it simpler for IIS to refuse to serve out those files, and for ASP.NET to react to changes in the file and automatically refresh all the name-value pairs.)
Class libraries (the assembly ends with .dll) can't use config files of their own—though they can use the config file of the application that is running when the assembly is loaded, which is fine if the class library serves a single application, or you can count on all the applications that use the assembly having the appropriate setting in the configuration file.
So, going forward, whenever you have a connection string or some other kind of setting you want to expose to your users, something you want to be able to change without recompiling the application, use a configuration file. It's simple and easy—you need to add the file to your project, add a post-build event, type a little XML, and you need one whole line of code in your app for each setting you want to get from the file. That's all it takes.
About the Author
Kate Gregory is a founding partner of Gregory Consulting Limited (www.gregcons.com). In January 2002, she was appointed MSDN Regional Director for Toronto, Canada. Her experience with C++ stretches back to before Visual C++ existed. She is a well-known speaker and lecturer at colleges and Microsoft events on subjects such as .NET, Visual Studio, XML, UML, C++, Java, and the Internet. Kate and her colleagues at Gregory Consulting specialize in combining software develoment with Web site development to create active sites. They build quality custom and off-the-shelf software components for Web pages and other applications. Kate is the author of numerous books for Que, including Special Edition Using Visual C++ .NET.