首页 > 其他分享 >在注册表中设置用户或系统环境变量的值

在注册表中设置用户或系统环境变量的值

时间:2023-12-22 16:37:23浏览次数:29  
标签:szVar MAX LPTSTR 用户 static szData 注册表 NULL 环境变量

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
// Copyright © 2022, 飞麦 <[email protected]>, All rights reserved.

// 程序: 在注册表中设置用户或系统环境变量的值
// 作者: 飞麦, mailto:[email protected], 2010-10-26~2023-12-22

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include "Shlwapi.h"  // StrStrI, PathFileExists, PathIsDirectory


#define show() Show(_T(__FILE__), __LINE__)


static const size_t MAX_DATA = MAX_PATH * 256;
static const size_t MAX_DIR = MAX_PATH * 16;

typedef TCHAR TypeData[MAX_DATA];
typedef TCHAR TypeDir[MAX_DIR];

// 可执行程序查找路径
static LPCTSTR PATH = _T("Path");
// Java 类查找路径
static LPCTSTR CLASSPATH = _T("ClassPath");
// Ruby 类查找路径
static LPCTSTR RUBYLIB = _T("RubyLib");
// 环境变量性质
static LPCTSTR szMode = _T("用户");

// 直接使用 stdout 难以正确输出非英文 Unicode 字符
static FILE* fout = NULL;
// 本程序运行结果输出文件
static TypeDir szLogFile;
// Unicode 编码文件头
static const TCHAR BOM = L'\xFEFF';
// 用户环境变量子键
static LPCTSTR USR_SUB_KEY = _T("Environment");
// 系统环境变量子键
static LPCTSTR SYS_SUB_KEY = _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment");
// 帮助信息
static LPCTSTR HELP_MSG =
_T("程序: envy\n")
_T("作者: 飞麦, mailto:[email protected], 2010-10-26~2023-12-22.\n")
_T("功能: 在注册表中设置、增加、减少、清除系统(/s)或用户(/u,默认)环境变量,涉及系统环境变量需以管理员身份运行。\n")
_T("用法: envy [/s|/u] var[+|-]=\"[item]\"\n")
_T("示例: envy RUBYLIB=\"C:\\R\" /s Path-=\"D:\\jdk1.5\\bin\" /u Path+=\"D:\\jdk1.6\\bin\" NOTHING=\"\"\n")
_T("解释: 1设置用户环境变量,2减少系统环境变量的值,3增加用户环境变量的值,4清除用户环境变量。\n")
_T("========================================\n");


// 打开日志文件
static bool log_on() {
    // 运行结果输出目录
    static TypeDir szLogDir;
    // 获取临时目录
    (void)GetTempPath(MAX_DIR, szLogDir);
    (void)_stprintf_s(szLogFile, MAX_DIR, _T("%s#envy.tmp"), szLogDir);
    // b 输出Unicode字符, 不影响type, 影响notepad(换行不加回车);t输出ANSI/MBCS字符(换行自动加回车)
    _tfopen_s(&fout, szLogFile, _T("wb"));
    if (fout == NULL) {
        // Only English is allowed in _tprintf
        _tprintf(_T("Fail on open %s for write.\n"), szLogFile);
        return false;
    }
    // TYPE 命令根据 BOM 来判断此文件是否为 Unicode 编码
    _ftprintf(fout, _T("%c%s"), BOM, HELP_MSG);
    return true;
}


// 关闭并显示日志文件
static void log_off() {
    (void)fclose(fout);

    static TypeDir szCmdLine;
    _stprintf_s(szCmdLine, MAX_DIR, _T("cmd.exe /c type %s"), szLogFile);
    STARTUPINFO startInfo;
    GetStartupInfo(&startInfo);
    PROCESS_INFORMATION proInfo;
    DWORD dwCreaFlags = CREATE_UNICODE_ENVIRONMENT;
    (void)CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, dwCreaFlags, NULL, NULL, &startInfo, &proInfo);
    (void)WaitForSingleObject(proInfo.hProcess, INFINITE);
    (void)CloseHandle(proInfo.hThread);
    (void)CloseHandle(proInfo.hProcess);
    (void)DeleteFile(szLogFile);
}


// 显示系统函数的错误信息
static bool Show(LPCTSTR szFile, int iLine) {
    DWORD dwMsgId = GetLastError();
    LPVOID lpMsgBuf = NULL;
    DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM;
    DWORD dwLangId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
    LPTSTR lpBuffer = LPTSTR(&lpMsgBuf);
    DWORD dwLen = FormatMessage(dwFlags, NULL, dwMsgId, dwLangId, lpBuffer, 0, NULL);
    LPCTSTR szMsg = dwLen > 0 ? LPTSTR(lpMsgBuf) : _T("\n");
    _ftprintf(fout, _T("文件=%s 行号=%d 编码=%lu 错误=%s"), szFile, iLine, dwMsgId, szMsg);
    (void)LocalFree(lpMsgBuf);
    return false;
}


// 查询注册表值
static bool getRegistry(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR szVar, LPDWORD pdwType, LPTSTR szData, LPDWORD lpcb) {
    HKEY hkResult;
    LONG lResult = RegOpenKeyEx(hKey, lpSubKey, NULL, KEY_QUERY_VALUE, &hkResult);
    if (lResult != ERROR_SUCCESS)
        (void)show();
    else {
        lResult = RegQueryValueEx(hkResult, szVar, NULL, pdwType, LPBYTE(szData), lpcb);
        if (lResult != ERROR_SUCCESS)
            (void)show();
        *lpcb /= sizeof(TCHAR);
        LONG lResult2 = RegCloseKey(hkResult);
        if (lResult2 != ERROR_SUCCESS) {
            (void)show();
            lResult = lResult2;
        }
    }
    return lResult == ERROR_SUCCESS;
}


// 设置注册表值
static bool setRegistry(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR szVar, DWORD dwType, LPTSTR szData, DWORD cb) {
    HKEY hkResult;
    LONG lResult = RegOpenKeyEx(hKey, lpSubKey, NULL, KEY_ALL_ACCESS, &hkResult);
    if (lResult != ERROR_SUCCESS)
        (void)show();
    else {
        cb *= sizeof(TCHAR);
        lResult = RegSetValueEx(hkResult, szVar, NULL, dwType, LPBYTE(szData), cb);
        if (lResult != ERROR_SUCCESS)
            (void)show();
        LONG lResult2 = RegCloseKey(hkResult);
        if (lResult2 != ERROR_SUCCESS) {
            (void)show();
            lResult = lResult2;
        }
    }
    return lResult == ERROR_SUCCESS;
}


// 删除注册表值
static bool delRegistry(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR szVar) {
    HKEY hkResult;
    LONG lResult = RegOpenKeyEx(hKey, lpSubKey, NULL, KEY_ALL_ACCESS, &hkResult);
    if (lResult != ERROR_SUCCESS)
        (void)show();
    else {
        lResult = RegDeleteValue(hkResult, szVar);
        if (lResult != ERROR_SUCCESS)
            (void)show();
        LONG lResult2 = RegCloseKey(hkResult);
        if (lResult2 != ERROR_SUCCESS) {
            (void)show();
            lResult = lResult2;
        }
    }
    return lResult == ERROR_SUCCESS;
}


// 将环境变量 szVar (值为 szData) 中的 szItem 消除掉, 再在后面加上 szItem
static void adjustEnvVariable(LPCTSTR szVar, TypeData szData, LPTSTR szItem) {
    // 判断 szVar 只是为了防止 Lint 告警,szItem 为空串时不需要处理
    if (*szItem == NULL || *szVar == NULL)
        return;
    // 可能为空串, 如 ClassPath 初始没有被设置
    static TypeData szDataPlus;
    // 分号是 Windows 的路径分隔符
    _stprintf_s(szDataPlus, MAX_DATA, _T(";%s%s"), szData, *szData == NULL ? _T("") : _T(";"));
    static TypeData szItemPlus;
    int iLen = _stprintf_s(szItemPlus, MAX_DATA, _T(";%s%s"), szItem, *szItem == NULL ? _T("") : _T(";"));
    // 将 szDataPlus 中的所有 szItemPlus 均替换为分号
    for (;;) {
        // 不区分大小写的查找, Windows 的路径不区分大小写
        LPTSTR szFind = StrStrI(szDataPlus, szItemPlus);
        // 如果找不到了则退出
        if (szFind == NULL)
            break;
        // 将一个 szItemPlus 替换为分号, 通过前后各增加分号, 确保被搜索串的唯一性与完整性
        _tcscpy_s(szFind + 1, MAX_DATA, szFind + iLen);
    }

    // 将 szDataPlus(不要前面的分号) 和 sItemPlus(不要前面的分号) 合并后放到 szData 中
    iLen = _stprintf_s(szData, MAX_DATA, _T("%s%s"), szDataPlus + 1, szItemPlus + 1);
    // 删除最后的分号
    szData[iLen - 1] = NULL;
}


// 清洁 szVar 环境变量, 将其中不存在的目录或文件清除
static void cleanEnvVariable(LPCTSTR szVar, LPTSTR szData) {
    // maximum characters in expanded string
    DWORD dwLenPath = MAX_DATA;
    static TypeData szExpData;
    dwLenPath = ExpandEnvironmentStrings(szData, szExpData, dwLenPath);
    if (dwLenPath == 0) {
        _ftprintf(fout, _T("%s=%s:扩展环境变量失败!"), szVar, szData);
        return;
    }
    LPTSTR szExpLoc = szExpData;
    LPTSTR szLoc = szData;
    static TypeData szTmpData;
    *szTmpData = NULL;
    for (;;) {
        LPTSTR szExpSemi = _tcschr(szExpLoc, static_cast<int>(_T(';')));
        LPTSTR szSemi = _tcschr(szLoc, static_cast<int>(_T(';')));
        static TypeData szExpDir;
        static TypeData szDir;
        if (szExpSemi == NULL && szSemi == NULL) {
            _tcscpy_s(szExpDir, MAX_DATA, szExpLoc);
            _tcscpy_s(szDir, MAX_DATA, szLoc);
        }
        else if (szExpSemi != NULL && szSemi != NULL) {
            *szExpSemi = NULL;
            _tcscpy_s(szExpDir, MAX_DATA, szExpLoc);
            *szExpSemi = _T(';');
            *szSemi = NULL;
            _tcscpy_s(szDir, MAX_DATA, szLoc);
            *szSemi = _T(';');
            szExpLoc = szExpSemi + 1;
            szLoc = szSemi + 1;
        }
        else {
            _ftprintf(fout, _T("%s=%s:扩展后分号数量不同!\n"), szVar, szData);
            return;
        }
        bool bJar = _tcsicmp(szVar, CLASSPATH) == 0 && PathFileExists(szExpDir);
        bool bDot = _tcscmp(szExpDir, _T(".")) == 0;
        bool bDir = PathIsDirectory(szExpDir);
        if (bJar || bDot || bDir) {
            if (*szTmpData != NULL)
                _tcscat_s(szTmpData, MAX_DATA, _T(";"));
            _tcscat_s(szTmpData, MAX_DATA, szDir);
        }
        else if (*szDir != NULL)
            _ftprintf(fout, _T("%s:目录或文件因不存在而被抛弃!\n"), szDir);
        if (szExpSemi == NULL)
            break;
    }
    _tcscpy_s(szData, MAX_DATA, szTmpData);
}


// 设置注册表值
// hKey: HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, ...
// lpSubKey: (HKEY_CURRENT_USER\\Environment, SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment)
// szVar: Path, Classpath, RUBYLIB, ...
// dwType: REG_EXPAND_SZ (%Path_HKCU%), REG_SZ, ...
// szData: D:\\jdk1.5\\bin, ...
// cb: length of szData
static bool setRegistry2(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR szVar, DWORD dwType, LPTSTR szData, int chgType) {
    static TypeData szNewData;
    if (chgType == 0)
        _tcscpy_s(szNewData, MAX_DATA, szData);
    else {
        static TypeData szOldData;
        DWORD cbData = MAX_DATA * sizeof(TCHAR);
        DWORD dwType0 = dwType;
        if (!getRegistry(hKey, lpSubKey, szVar, &dwType0, szOldData, &cbData)) {
            if (chgType == 1)
                _tcscpy_s(szNewData, MAX_DATA, szData);
            else
                *szNewData = NULL;
        }
        else {
            if (chgType == 1) {
                _tcscpy_s(szNewData, MAX_DATA, szOldData);
                adjustEnvVariable(szVar, szNewData, szData);
            }
            else {
                _stprintf_s(szNewData, MAX_DATA, _T(";%s%s"), szOldData, *szOldData == NULL ? _T("") : _T(";"));
                static TypeData szItemPlus;
                // 分号是 Windows 的路径分隔符
                int iLen = _stprintf_s(szItemPlus, MAX_DATA, _T(";%s;"), szData);
                // 将 szNewData 中的所有 szItemPlus 均替换为分号
                for (;;) {
                    // 不区分大小写的查找, Windows 的路径不区分大小写
                    LPTSTR szFind = StrStrI(szNewData, szItemPlus);
                    if (szFind == NULL)
                        // 如果找不到了则退出
                        break;
                    // 将一个 szItemPlus 替换为分号,通过前后各增加分号, 确保被搜索串的唯一性与完整性
                    _tcscpy_s(szFind + 1, MAX_DATA, szFind + iLen);
                }
            }
        }
    }
    if (*szNewData == NULL) {
        _ftprintf(fout, _T("删除环境变量:%s\n"), szVar);
        return delRegistry(hKey, lpSubKey, szVar);
    }
    if (_tcsicmp(szVar, PATH) == 0 || _tcsicmp(szVar, CLASSPATH) == 0 || _tcsicmp(szVar, RUBYLIB) == 0)
        cleanEnvVariable(szVar, szNewData);
    _ftprintf(fout, _T("设置%s环境变量 %s 为 %s\n"), szMode, szVar, szNewData);
    DWORD cb = DWORD(_tcslen(szNewData) + 1);
    return setRegistry(hKey, lpSubKey, szVar, dwType, szNewData, cb);
}


// 设置 szVar 环境变量的值为 szData
static bool setEnvVariable(LPCTSTR szVar, LPTSTR szData, int chgType) {
    if (_tcscmp(szMode, _T("系统")) == 0)
        return setRegistry2(HKEY_LOCAL_MACHINE, SYS_SUB_KEY, szVar, REG_EXPAND_SZ, szData, chgType);
    else
        return setRegistry2(HKEY_CURRENT_USER, USR_SUB_KEY, szVar, REG_EXPAND_SZ, szData, chgType);
}


// 处理单个环境变量
static int deal(LPTSTR szVarExpr) {
    LPTSTR szEqu = _tcschr(szVarExpr, int(_T('=')));
    LPCTSTR szAction = _T("设置");
    LPCTSTR szBy = _T("为");
    LPTSTR szVarTail = NULL;
    int chgType = 0;
    if (szEqu == NULL) {
        _ftprintf(fout, _T("参数 %s 中应有等号!\n"), szVarExpr);
        return 3;
    }
    else if (szEqu == szVarExpr) {
        _ftprintf(fout, _T("参数 %s 中等号前应有环境变量名!\n"), szVarExpr);
        return 4;
    }
    else if (*(szEqu - 1) == _T('+')) {
        *(szEqu - 1) = NULL;
        szVarTail = szEqu - 2;
        chgType = 1;
        szAction = _T("增加");
        szBy = _T("用");
    }
    else if (*(szEqu - 1) == _T('-')) {
        *(szEqu - 1) = NULL;
        szVarTail = szEqu - 2;
        chgType = -1;
        szAction = _T("减少");
        szBy = _T("以");
    }
    else {
        *szEqu = NULL;
        szVarTail = szEqu - 1;
    }
    LPTSTR szVar = szVarExpr;
    while (*szVar == _T(' '))
        szVar++;
    while (*szVarTail == _T(' '))
        *szVarTail-- = NULL;
    LPTSTR szData = szEqu + 1;
    while (*szData == _T(' '))
        szData++;
    LPTSTR szNil = _tcschr(szData, 0);
    if (szNil != NULL) {
        LPTSTR szDataTail = szNil - 1;
        while (*szDataTail == _T(' '))
            *szDataTail-- = NULL;
    }
    int iRe = setEnvVariable(szVar, szData, chgType) ? 0 : 3;
    LPCTSTR szRes = iRe == 0 ? _T("成功。") : _T("失败!");
    _ftprintf(fout, _T("%s%s环境变量 %s %s %s:%s\n"), szAction, szMode, szVar, szBy, szData, szRes);
    return iRe;
}


// 广播环境变量到所有窗口
static int broadcast() {
    DWORD_PTR pdwRetValue = NULL;
    LPARAM param = (LPARAM)_T("Environment");
    LRESULT iR = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, param, SMTO_ABORTIFHUNG, 5000, &pdwRetValue);
    // 若出错
    if (iR == 0) {
        (void)show();
        _ftprintf(fout, _T("广播环境变量到所有窗口时出错!\n"));
        return 1;
    }
    return 0;
}


// 命令行参数是否含有 /s 选项
static bool has_sys_opt(int argc, LPTSTR argv[]) {
    for (int i = 1; i < argc; i++)
        if (lstrcmpi(argv[i], _T("/s")) == 0)
            return true;
    return false;
}


// 是否有管理员权限
static bool has_admin_right() {
    HKEY hkResult;
    LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SYS_SUB_KEY, NULL, KEY_ALL_ACCESS, &hkResult);
    bool ok = lResult == ERROR_SUCCESS;
    if (ok)
        (void)RegCloseKey(hkResult);
    return ok;
}


// 处理命令行参数
static int inner(int argc, LPTSTR argv[]) {
    if (argc <= 1)
        return 1;
    int iRet = 0;
    if (has_sys_opt(argc, argv) && !has_admin_right()) {
        _ftprintf(fout, _T("当使用 /s 选项时,应以管理员身份运行。\n"));
        return 9;
    }
    for (int i = 1; i < argc; i++) {
        if (*argv[i] == _T('/')) {
            if (lstrcmpi(argv[i], _T("/s")) == 0)
                szMode = _T("系统");
            else if (lstrcmpi(argv[i], _T("/u")) == 0)
                szMode = _T("用户");
            else
                _ftprintf(fout, _T("%s:错误选项!\n"), argv[i]);
        }
        else
            iRet += deal(argv[i]);
    }
    iRet += broadcast();
    return iRet;
}


// 主程序
int _tmain(int argc, LPTSTR argv[]) {
    if (!log_on())
        return 2;
    int iRet = inner(argc, argv);
    log_off();
    return iRet;
}

标签:szVar,MAX,LPTSTR,用户,static,szData,注册表,NULL,环境变量
From: https://www.cnblogs.com/fitmap/p/17921884.html

相关文章

  • adb root权限 su 超级用户执行命令
    前言全局说明adbrootsu超级用户执行命令一、方法一adbshellsu-csetpropservice.adb.tcp.port5555二、方法二adbshellsu0"setpropservice.adb.tcp.port5555"三、四、免责声明:本号所涉及内容仅供安全研究与教学使用,如出现其他风险,后果自负。......
  • APP如果想要分发给用户去使用,怎么办?
    无论是安卓的应用还是iOS的应用,所有的APP如果想要分发给用户去使用,都必须要上架到应用商店或者是分发平台进行操作。对于安卓的APP还比较好一些,可以申请上架到应用商店,也可以直接把apk上传到分发平台,生成二维码或者短链接就可以使用。苹果开发者就没这个好运气了,上架AppStore是......
  • 用户组
    用户和组:Linux下可以创建多个用户,可以用组进行管理用户比如:男生组boysming bo gang qiang女生组girlsfang hong yue yuan1.创建组groupadd boys2.创建用户useradd -m -g boys ming其中-g表示在添加用户,同时将......
  • 超级用户
    超级用户:超级用户root切换到root用户,有全部权限,可以直接useradd等命令。 1.给超级用户root添加密码,并切换至root用户2.每条命令前加上sudo代表使用超级用户执行命令,可以不切换至root用户下......
  • 添加用户
    添加用户:添加用户命令:sudouseradd-mtest1其中,sudo,用来表示以管理员身份执行1.如果直接执行useradd-mtest1报错:   2.添加用户命令:sudo useradd -m 用户名(其中 -m参数表示在/home下添加用户目录)  3.修改用户密码:sudo pass......
  • cmd命令行设置 windows 设置环境变量
    设置用户级别的环境变量::设置新参数JAVA_HOME1setxJAVA_HOME1"c:\test";exit;echo"%JAVA_HOME1%";::追加参数内容JAVA_HOME1setxJAVA_HOME1"%JAVA_HOME1%;c:\test2\;";exit;echo"%JAVA_HOME1%";::追加到Pathsetxpath"%pat......
  • postgresql常用创建用户和授权
    需求(1)给用户a创建一个数据库,并且给a用户对这个库有所有权限(2)给read_a用户对这个数据库有只读权限步骤1.创建用户a2.创建数据库db_a,并设置owner为a3.回收默认的publicschemacreate权限4.设置db_a的publicschema默认的owner为a5.创建只读用户read_a6.用a用户给read_a......
  • Odoo中防止用户同一时间多次点击同一按钮触发函数
    我们将探讨如何在Odoo中实现一个全局防重复点击功能,以防止用户在短时间内重复点击按钮而触发多次函数调用。这种情况通常发生在用户不断快速点击同一个按钮时,导致后端函数被多次调用,可能会引起数据错误或性能问题。在Odoo中,我们可以通过自定义模块来实现这个功能。首先,我们需要在bu......
  • 获取指定用户的所有待办流程
    SELECT (CASErequestlevelWHEN0THEN0WHEN1THEN1WHEN2THEN2ELSE-1END)ASrequestlevelorder, requestid, requestmark, createdate, createtime, creater, creatertype, workflowid, requestname, requestnamenew, STATUS, requestlevel, cur......
  • Mac 环境变量
    成功路上并不拥挤,因为坚持的人并不多。只有坚持了,我们才知道,这一路上有多少事情需要实干,有多少东西需要学习。1.环境变量的理解环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,如临时文件夹位置、系统文件夹位置以及某些应用软件文件的路径等等。环境变量......