基本概念

GetEnvironmentStringsFreeEnvironmentStringsWindows API中成对使用的环境变量操作函数:前者用于获取当前进程的「所有环境变量完整缓冲区」,后者用于释放该缓冲区,核心是实现「安全遍历所有环境变量」并避免内存泄漏。
GetEnvironmentStrings:分配一块内存,存储当前进程的所有环境变量(格式:NULL分隔的字符串列表,结尾双NULL终止),返回缓冲区指针。
FreeEnvironmentStrings:释放GetEnvironmentStrings分配的缓冲区,回收系统资源。

强制规则:
GetEnvironmentStrings分配的缓冲区,能通过FreeEnvironmentStrings释放(不可释放malloc/LocalAlloc等手动分配的内存);
缓冲区需「分配一次 + 释放一次」,重复释放会导致内存损坏,不释放会导致资源泄漏;
释放后,原缓冲区指针失效,不可再访问(避免野指针操作)。

基本语法

1
2
3
4
5
6
7
8
9
10
11
12
13
// GetEnvironmentStrings(分配缓冲区)
// Unicode 版本
LPWSTR GetEnvironmentStringsW();

// ANSI 版本
LPTCH GetEnvironmentStringsA();

// FreeEnvironmentStrings(释放缓冲区)
// Unicode 版本(对应 GetEnvironmentStringsW)
BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock);

// ANSI 版本(对应 GetEnvironmentStringsA)
BOOL FreeEnvironmentStringsA(LPTCH lpszEnvironmentBlock);

环境变量缓冲区格式

GetEnvironmentStringsW返回的缓冲区是连续内存块,格式规则:
1.每个环境变量以Unicode字符串存储(如L"PATH=C:\\Windows\\system32");
2.变量之间以单个\0(空字符)分隔;
3.整个缓冲区以两个连续\0结尾(遍历终止条件);
4.部分系统环境变量可能以=开头(如L"=C:=C:\\Windows"),表示驱动器当前目录,属于正常格式。

示例:

1
2
3
4
L"ALLUSERSPROFILE=C:\\ProgramData\0"  // 变量 1
L"APPDATA=C:\\Users\\XXX\\AppData\\Roaming\0" // 变量 2
L"PATH=C:\\Windows\\system32;...\0" // 变量 3
L"\0" // 缓冲区结尾(双 \0)

具体示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <windows.h>
#include <stdio.h>
#include <wchar.h>

int main() {
// 1. 分配环境变量缓冲区(Unicode 版本)
LPWSTR lpEnvBlock = GetEnvironmentStringsW();
if (lpEnvBlock == NULL) {
printf("GetEnvironmentStringsW 失败,错误码:%d\n", GetLastError());
return 1;
}

// 2. 遍历缓冲区(核心:按 \0 分割变量)
LPWSTR lpCurrent = lpEnvBlock; // 指针指向当前变量
printf("当前进程的所有环境变量(Unicode):\n");
printf("-------------------------------------------------------------------------\n");

int nCount = 0; // 统计环境变量个数
while (*lpCurrent != L'\0') { // 终止条件:遇到第一个 \0(缓冲区结尾前的最后一个变量)
wprintf(L"[%d] %ls\n", ++nCount, lpCurrent);
// 移动指针到下一个变量(跳过当前变量 + 末尾 \0)
lpCurrent += wcslen(lpCurrent) + 1;
}

printf("-------------------------------------------------------------------------\n");
printf("共找到 %d 个环境变量\n", nCount);

// 3. 释放缓冲区(必须步骤,不可遗漏)
BOOL bResult = FreeEnvironmentStringsW(lpEnvBlock);
if (bResult) {
printf("缓冲区释放成功\n");
} else {
printf("缓冲区释放失败,错误码:%d\n", GetLastError());
}
lpEnvBlock = NULL; // 标记指针无效,避免误访问

return 0;
}