环境变量是进程中一组变量信息,环境变量分为系统环境变量、用户环境变量和进程环境变量。系统有全局的环境变量,在进程创建时,进程继承了系统的全局环境变量、当前登录用户的用户环境变量和父进程的环境变量。进程也可以有自己的环境变量。
设置和获取所在进程的环境变量使用API函数GetEnvironmentStrings、GetEnvironmentVariable和SetEnvironmentVariable:
1)GetEnvironmentStrings函数用于获取所有环境变量字符串:
LPTCH WINAPI GetEnvironmentStrings(void);
返回值:
成功时,返回指向保存环境变量的缓冲区;
失败时,返回值为NULL。
2)FreeEnvironmentStrings函数用来释放由GetEnvironmentStrings返回的内存块:
BOOL WINAPI FreeEnvironmentStrings(
__in LPTCH lpszEnvironmentBlock
);
返回值:
成功时,返回非零值;
失败时,返回零值,可调用GetLastError()查看进一步错误消息。
3)GetEnvironmentVariable函数用于获取指定的环境变量:
DWORD WINAPI GetEnvironmentVariable(
__in_opt LPCTSTR lpName, //环境变量名
__out_opt LPTSTR lpBuffer, //指向保存环境变量值的缓冲区
__in DWORD nSize //缓冲区大小(字符数)
);
返回值:
成功时,返回真实的环境变量值大小,不包括null结束符;
如果lpBuffer大小不足,则返回值是实际所需的字符数大小,lpBuffer内容未定义;
失败时,返回0;如果指定的环境变量找不到,GetLastError()返回ERROR_ENVVAR_NOT_FOUND。
4)SetEnvironmentVariable函数用于设置指定的环境变量:
BOOL WINAPI SetEnvironmentVariable(
__in LPCTSTR lpName, //环境变量名,当该值不存在且lpValue不为NULL时,将创建一个新的
__in_opt LPCTSTR lpValue //环境变量值
);
返回值:
成功时,返回非零值;
失败时,返回零值,调用GetLastError()查看具体的错误信息。
该函数对系统环境变量以及其他进程的环境变量不起作用!
实例一:调用GetEnvironmentStrings函数检索进程的环境变量内存块,并将其中内容打印到控制台:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int _tmain()
{
LPTSTR lpszVariable;
LPTCH lpvEnv;
//获得环境变量内存块的指针
lpvEnv = GetEnvironmentStrings();
if(lpvEnv == NULL)
{
printf("GetEnvironmentStrins failed(%d)/n", GetLastError());
return 0;
}
//环境变量字符串是以NULL分隔的,内存块以NULL结尾
lpszVariable = (LPTSTR)lpvEnv;
while(*lpszVariable)
{
_tprintf(TEXT("%s/n"), lpszVariable);
lpszVariable += lstrlen(lpszVariable) + 1; //移动指针
}
FreeEnvironmentStrings(lpvEnv);
system("pause");
return 1;
}
实例二:默认情况下,子进程继承父进程环境变量内存块的一份拷贝;下面代码通过调用CreateProcess函数实现将一个环境变量块传递给子进程(asce.exe就是实例一编译链接得到的exe文件,因此,该代码的运行结果就是子进程打印从父进程继承而来的环境变量):
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFSIZE 4096
int _tmain()
{
TCHAR chNewEnv[BUFSIZE];
LPTSTR lpszCurrentVariable;
DWORD dwFlags = 0;
TCHAR szAppName[] = TEXT("asce.exe");
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL fSuccess;
//将环境变量字符串拷贝到环境变量内存块中
lpszCurrentVariable = (LPTSTR)chNewEnv;
if(FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("AsceSetting=Luffy"))))
{
printf("String copy failed/n");
return FALSE;
}
lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
if(FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("AsceVersion=2.0"))))
{
printf("String copy failed/n");
return FALSE;
}
//使环境变量内存块以NULL结尾
lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
*lpszCurrentVariable = (TCHAR)0;
//创建子进程,指定一个新的环境变量内存块
SecureZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
#ifdef UNICODE
dwFlags = CREATE_UNICODE_ENVIRONMENT;
#endif
fSuccess = CreateProcess(szAppName, NULL, NULL, NULL,
TRUE, dwFlags, (LPVOID)chNewEnv, //新的环境变量内存块
NULL, &si, &pi);
if(!fSuccess)
{
printf("CreateProcess failed(%d)/n", GetLastError());
return FALSE;
}
WaitForSingleObject(pi.hProcess, INFINITE);
system("pause");
return TRUE;
}
实例三:在子进程创建过程中改变子进程的环境变量是一个进程改变另一个进程环境变量的唯一方式。一个进程绝不能直接改变另一个进程(非子进程)的环境变量。下面代码实现子进程继承符进程环境变量的方法:
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#define BUFSIZE 4096
#define VARNAME TEXT("AsceVariable")
int _tmain()
{
DWORD dwRet, dwErr;
LPTSTR pszOldVal;
TCHAR szAppName[] = TEXT("asce.exe");
DWORD dwFlags = 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL fExist, fSuccess;
// Retrieves the current value of the variable if it exists.
// Sets the variable to a new value, creates a child process,
// then uses SetEnvironmentVariable to restore the original
// value or delete it if it did not exist previously.
pszOldVal = (LPTSTR)malloc(BUFSIZE*sizeof(TCHAR));
if(NULL == pszOldVal)
{
printf("Out of memory/n");
return FALSE;
}
dwRet = GetEnvironmentVariable(VARNAME, pszOldVal, BUFSIZE);
if(0 == dwRet)
{
dwErr = GetLastError();
if(ERROR_ENVVAR_NOT_FOUND == dwErr)
{
printf("Environment variable does not exist/n");
fExist = FALSE;
}
}
else if(BUFSIZE < dwRet)
{
pszOldVal = (LPTSTR)realloc(pszOldVal, dwRet*sizeof(TCHAR));
if(NULL == pszOldVal)
{
printf("Out of memory/n");
return FALSE;
}
dwRet = GetEnvironmentVariable(VARNAME, pszOldVal, dwRet);
if(!dwRet)
{
printf("GetEnvironmentVariable failed(%d)/n", GetLastError());
return FALSE;
}
else
fExist = TRUE;
}
else
fExist = TRUE;
//Set a value for the child process to inherit
if(!SetEnvironmentVariable(VARNAME, TEXT("ASCE")))
{
printf("SetEnvironmentVariable failed(%d)/n", GetLastError());
return FALSE;
}
//Create a child process
SecureZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
#ifndef UNICODE
dwFlags = CREATE_UNICODE_ENVIRONMENT;
#endif
fSuccess = CreateProcess(szAppName, NULL, NULL, NULL,
TRUE, dwFlags, NULL,//inherit parent's environment
NULL, &si, &pi);
if(!fSuccess)
{
printf("CreateProcess failed(%d)/n", GetLastError());
}
WaitForSingleObject(pi.hProcess, INFINITE);
//Restore the original environment variable
if(fExist)
{
if(!SetEnvironmentVariable(VARNAME, pszOldVal))
{
printf("SetEnvironmentVariable failed(%d)/n", GetLastError());
return FALSE;
}
}
else
SetEnvironmentVariable(VARNAME, NULL);
free(pszOldVal);
system("pause");
return fSuccess;
}