Enumerating Environment variables

One of the way to enumerate the Environment Variables is by accessing _environ global variable. The GetEnvironmentStrings function provides another way by returning a pointer to the environment block of the calling process. It can also be done using WMI Win32_Environment Class.

The Windows API support class is used to handle Windows API structures.

This is sample code. Add error handling and adjust to your requirements as necessary.

Retrieve the list of Environment Variables at the time when Windows started.
A handy Array Browser utility that displays an array content is used in above code to see the result list.

#DEFINE ccEnvVarName 1
#DEFINE ccEnvVarValue 2
 
DECLARE Long GetModuleHandle IN win32api String
DECLARE Long GetProcAddress IN win32api Long, String
 
loWas = NEWOBJECT("WinApiSupport", "WinApiSupport.fxp")
 
* Get pointer to the process environment
lnHandle = GetModuleHandle("msvcrt.dll")
lnPtr = GetProcAddress(lnHandle,"_environ")
* It is a pointer to an array of pointers to the environment variables strings
lnPtr = loWas.Long2NumFromBuffer(lnPtr)
 
lnInd = 0
DO WHILE .T.
	* Pointer to the next environment variable string
	lnAddress = loWas.Long2NumFromBuffer(lnPtr + lnInd * 4)
	IF lnAddress = 0 
		EXIT
	ENDIF
 
	* Increment it now so we can use it to resize the array
	lnInd = lnInd + 1
	DIMENSION laEnvVars[lnInd, 2]
	* Copy string to a memory variable
	lcEnvItem = loWas.StrZCopy(lnAddress)
	* Extract variable name
	laEnvVars[m.lnInd, ccEnvVarName] = GETWORDNUM(lcEnvItem,1,"=")
	* Get variable value
	laEnvVars[m.lnInd, ccEnvVarValue] = GETWORDNUM(lcEnvItem,2,"=")
	*laEnvVars[m.lnInd, ccEnvVarValue] = GETENV(laEnvVars[m.lnInd, ccEnvVarName])
ENDDO
 
* Displays the array content in a Browser
= browarr(@laEnvVars)

Retrieve the list of Environment Variables for the current process at the time when application started. The list can be changed by application using SetEnvironmentVariable function.

#DEFINE ccEnvVarName 1
#DEFINE ccEnvVarValue 2
 
DECLARE Long GetEnvironmentStrings IN WIN32API 
DECLARE Long FreeEnvironmentStrings IN WIN32API Long lpszEnvironmentBlock
 
loWas = NEWOBJECT("WinApiSupport", "WinApiSupport.fxp")
 
* Get current process environment variables block
lnPtr = GetEnvironmentStrings()
 
lnAddress = lnPtr 
lnInd = 1
DO WHILE .T.
	* Copy string to a memory variable
	lcEnvItem = loWas.StrZCopy(lnAddress )
	IF EMPTY(lcEnvItem)
		EXIT
	ENDIF
 
	DIMENSION laEnvVars[lnInd, 2]
	* Extract variable name
	laEnvVars[m.lnInd, ccEnvVarName] = GETWORDNUM(lcEnvItem,1,"=")
	* Get variable value
	laEnvVars[m.lnInd, ccEnvVarValue] = GETWORDNUM(lcEnvItem,2,"=")
	*laEnvVars[m.lnInd, ccEnvVarValue] = GETENV(laEnvVars[m.lnInd, ccEnvVarName])
 
	* Next item
	lnAddress = lnAddress + LEN(lcEnvItem) + 1
	* Increment 
	lnInd = lnInd + 1
 
ENDDO
 
* Release the environment variables block
= FreeEnvironmentStrings(lnPtr)
 
* Displays the array content in a Browser
= browarr(@laEnvVars)

Creating, Setting, Deleting and Reading of Environment variables

CLEAR
 
* Create/Set/Delete a variable
DECLARE Long SetEnvironmentVariable IN WIN32API String lpName, String lpValue
* Add one
= SetEnvironmentVariable("MyVar01", "MyVal 01")
* Add one more
= SetEnvironmentVariable("MyVar02", "MyVal 02")
* Delete one
= SetEnvironmentVariable("MyVar02", Null)
 
? GetEnvVar("MyVar01")
? GetEnvVar("MyVar02")
? GetEnvVar("OS")
 
RETURN
 
* The function returns value of an environment variable of the current process including the ones created with SetEnvironmentVariable. 
*  The GETENV() function does not return values for the later.
FUNCTION GetEnvVar(tnVarName)
LOCAL lcBuffer, lnLen, lcVarVal
	* Read a variable
	DECLARE Long GetEnvironmentVariable IN WIN32API String lpName, String @lpBuffer, Long nSize
	lcBuffer = SPACE(4096)
	lnLen = GetEnvironmentVariable(tnVarName, @lcBuffer, LEN(lcBuffer))
	lcVarVal = ""
	IF lnLen > 0
		lcVarVal = LEFT(lcBuffer, lnLen)
	ENDIF
	RETURN lcVarVal
ENDFUNC

Retrieve the list of Environment Variables using WMI.

SET MEMOWIDTH TO 1024
CLEAR
 
LOCAL loWMI, loEnvCol, loEnvVar
loLocator	= CREATEOBJECT('WbemScripting.SWbemLocator')
loWMI		= loLocator.ConnectServer()
loEnvCol	= loWMI.ExecQuery("select * from Win32_Environment")
 
FOR EACH  loEnvVar in loEnvCol
	WITH loEnvVar
		? .Name, .SystemVariable AT 25, .UserName, .VariableValue
	ENDWITH 
ENDFOR 
No votes yet

Missing Function or incorrect name

There is no function: loWas.StrZCopy(lnAddress )
in the WinAPIsupport code.
Perhaps you meant: loWas.StrZFromBuffer ??

Missing method

I forgot to update the WinAPIsupport class code. Sorry about that. The missing code is below. You can add it to the class or you can copy the whole updated class.

	* Retrieve zero-terminated string 
	FUNCTION StrZCopy(tnPointer)
		LOCAL lcStr, lnStrPointer
		lcStr = SPACE(4096)
		lstrcpy(@lcStr, tnPointer)
		RETURN LEFT(lcStr, AT(CHR(0),lcStr)-1)
	ENDFUNC

Missing method - Thank you!

Thank you!
Works Great.