每个进程都有一个与它关联的环境块,这是在进程地址空间内分配的一块内存。
每个字符串的第一部分是一个环境变量的名称,后跟一个等号,等号之后是希望赋给此变量的值,注意:除了第一个=::=::\字符串,块中可能还有其他字符串是以(=)开头的。这种字符串不能作为环境变量的使用。
调用GetEnvironmentStrings函数来获取完整的环境块。
- PTSTR env = GetEnvironmentStrings();
-
- TCHAR key[MAX_PATH];
- TCHAR value[MAX_PATH];
- PTSTR cur = env;
- HRESULT hr = S_OK;
-
- PCTSTR pszPos = NULL;
- int current = 0;
-
- while (cur != NULL)
- {
- if (*cur != TEXT('='))
- {
- pszPos = _tcschr(cur, TEXT('='));
- pszPos++;
-
- size_t cbNameLength = (size_t)pszPos - (size_t)cur - sizeof(TCHAR);
- hr = StringCbCopyN(key, MAX_PATH, cur, cbNameLength);
- if (FAILED(hr))
- {
- break;
- }
-
- hr = StringCchCopyN(value, MAX_PATH, pszPos, _tcslen(pszPos) + 1);
-
- if (SUCCEEDED(hr))
- {
- _tprintf(TEXT("[%u] %s=%s\r\n"), current, key, value);
- }
- else
- {
- if (hr == STRSAFE_E_INSUFFICIENT_BUFFER)
- {
- _tprintf(TEXT("[%u] %s=%...s\r\n"), current, key, value);
- }
- else
- {
- _tprintf(TEXT("[%u] %s=???\r\n"), current, key);
- break;
- }
- }
- }
- else
- {
- _tprintf(TEXT("[%u] %s\r\n"), current, cur);
- }
-
- current++;
- while (*cur != TEXT('\0'))
- cur++;
-
- cur++;
-
- if (*cur == TEXT('\0'))
- break;
- }
以=开头的无效字符串会被跳过。其他每个有效的字符串会被逐一解析。‘=’字符被用作名称与值之间的分隔符。
如果不再需要GetEnvironmentStrings函数返回的内存块,应调用FreeEnvironmentStrings释放。
- DWORD dwResult = GetEnvironmentVariableW(
- _In_opt_ LPCWSTR lpName,
- _Out_writes_to_opt_(nSize,return + 1) LPWSTR lpBuffer,
- _In_ DWORD nSize
- );
参数1:指向查找的变量名称。
参数2:指向保持变量值的缓冲区。
参数3:指出缓冲区的大小(字符数)。
如果找到变量名,此函数返回复制到缓冲区的字符数;如果没有找到就返回0。
示例:
- void PrintEnvironmentVariable(PCTSTR name)
- {
- PTSTR value = NULL;
- DWORD dwResult = GetEnvironmentVariable(name, value, 0);
- if (dwResult)
- {
- DWORD size = dwResult * sizeof(TCHAR);
- value = (PTSTR)malloc(size);
- GetEnvironmentVariable(name, value, size);
- _tprintf(TEXT("%s=%...s\r\n"), name, value);
- free(value);
- }
- else
- {
- _tprintf(TEXT("%s unknown\r\n"), name);
- }
- }
由于我们不知道需要多少个字符来保持一个环境变量的值,所以第一次参数3传入0,它会返回所需要字符的数量。
在许多字符串的内部,都包含了“可替换的字符串”。例:
%USERPROFILE%\Documents
两个%中间的就是“可替换的字符串”,不同的机器上,值会不一样,比如我的就是C:\Users\wzz\Documents。
Windows提供了ExpandEnvironmentStrings函数来解析。函数原型如下:
- ExpandEnvironmentStringsW(
- _In_ LPCWSTR lpSrc,
- _Out_writes_to_opt_(nSize,return) LPWSTR lpDst,
- _In_ DWORD nSize
- );
参数1:一个包含一个或多个环境变量字符串的缓冲区,格式为: %variableName%
参数2:一个指向缓冲区的指针,用于接收在lpSrc缓冲区中展开环境变量字符串的结果。
参数3:lpDst参数所指向的缓冲区中可以存储的最大字符数。示例:
- DWORD chValue = ExpandEnvironmentStrings(TEXT("%USERPROFILE%"), NULL, 0);
- PTSTR buffer = new TCHAR[chValue];
-
- chValue = ExpandEnvironmentStrings(TEXT("%USERPROFILE%"), buffer, chValue);
-
- delete[] buffer;
由于我们不知道需要多少个字符来保持一个环境变量的值,所以第一次参数3传入0,它会返回所需要字符的数量。
- BOOL SetEnvironmentVariableW(
- [in] LPCWSTR lpName,
- [in, optional] LPCWSTR lpValue
- );
这个函数可以添加变量、删除变量、修改变量。