Accessing Environment Variables

How do I access the values of custom environment variables from within my application?


January 07, 2005
URL:http://www.drdobbs.com/windows/accessing-environment-variables/184405956

Accessing Environment Variables

Windows Q&A
January 7, 2005


Accessing Environment Variables

How do I access the values of custom environment variables from within my application?

Many applications (particularly older ones) utilize environment variables to customize their configuration or alter their execution. They have the advantage of being easy to specify and modify, are simple, and are widely understood by developers (and quite a few users). Early versions of Windows used environment variables extensively, although the practice has fallen out of use somewhat with alternate ways to specify such information, such as file-based designs (.INI, .NET’s .config, custom XML, etc.), programmatic designs (COM Automation, plugins, etc.), and the registry. However, they are still used even by the newest tools such as Visual Studio .NET 2003 (PATH, LIB, INCLUDE, TEMP, etc.).

Creating or modifying environment variables through the Windows UI is simple, although it has changed over the years and various releases of Windows. On this Windows XP machine I’m writing on, I click on the properties menu item for My Computer and see the following:

Figure 1: My Computer Properties

Clicking on the Environment Variables button shows the following dialog:

Figure 2: Environment Variables

The dialog’s buttons make it pretty clear how to add, edit, and remove variables. Typically, but not always, a variable will accommodate multiple values by separating them with semicolons—the PATH variable is the most famous one for doing this. However, there are examples such as the TEMP variable that only accommodate a single value.

Assuming your application needs to access a variable from the environment—whether a custom one you created yourself or a common one such as TEMP—the process is straightforward. The Windows SDK provides a function named ExpandEnvironmentStrings, which takes three parameters—the first is the environment variable you want to expand, the second is a buffer that will be updated with the variable’s current value, and the third is the size of the buffer passed in. If you are unsure of the size of the value that may be set for the variable, it’s best to use a large size like 32K or greater.

Here’s some code to illustrate:

std::string GetEnvVar(std::string sVar)
{
	char buffer[32000];
	ZeroMemory(buffer,sizeof(buffer));
	ExpandEnvironmentStrings( sVar.c_str(),buffer,sizeof(buffer) );
	sVar = buffer;
}

void main() { std::string sValue= GetEnvVar( "%PATH%); }

Notice the use of the % symbol to wrap the variable that is needed. This is required by the API. Not doing so will call the function to fail and return nothing but zero, indicating an error. However, we'll see a bit later why the use of the % symbol adds horsepower to this function.

An alternative is to call the function and rely on the return value to indicate the size that is needed—an initial call with a buffer size of 0 will return a DWORD with the number of bytes necessary to contain the value. A subsequent call can then be made with the proper size buffer.

Here’s some final code that shows this:

std::string GetEnvVar(std::string sVar)
{
	std::string sRet;
	char* buffer = NULL;
	DWORD sz = ExpandEnvironmentStrings( sVar.c_str(),buffer,0 );
	if ( sz > 0 )
	{
		buffer = new char[ sz+1 ];
		ZeroMemory(buffer,sz+1);
		ExpandEnvironmentStrings( sVar.c_str(),buffer,sz );
		sRet = buffer;
		delete []buffer;
	}
	return sRet;
}

It takes a bit more code to handle allocating the necessary RAM, but obviously this code is more robust than hardwiring the buffer size to 32K or so.

If the variable doesn’t exist in the environment, ExpandEnvironmentStrings returns 0, indicating an error condition. The function is also case-insensitive when looking up variables, which is handy—most of the time, they are uppercase from tradition, but sometimes you find mixed or lowercase ones.

A final tip about ExpandEnvironmentStrings—the first parameter may contain one or more environment variables embedded in a string. Any variables that are found in the environment are replaced in the passed string with their values. This can be useful if you want to blindly pass in values (such as command-line strings), which may or may not have environment variable references and just have them expanded before you begin processing. Nonenvironment variable text is ignored and unaffected. This is the reason behind why the environment variables passed in the first parameter must be wrapped with the % symbol—it allows the parser inside the function to find the variables since they must follow a specific format.


Mark M. Baker is the Chief of Research & Development at BNA Software located in Washington, D.C.
Do you have a Windows development question? Send it to [email protected].


Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.