我有一个 Windows 控制台可执行文件(称为 SetEnvX.exe),用于设置环境变量。它在内部调用 Windows API 中的
SetEnvironmentVariable
。调用成功。
在执行 SetEnvX.exe 的父 CMD 实例中,如果在 SetEnvX.exe 之后立即运行
SET
,则它创建的环境变量不存在。
如果我用以下行创建一个 TEST.CMD
SetEnvX.exe
set
TEST.CMD 中
SET
命令的输出也不显示 SetEnvX.exe 创建的环境变量。
SetEnvX.exe 等程序如何创建在执行该程序的交互式 CMD shell 或批处理文件范围内存在的环境变量?换句话说,我不想将环境变量放入全局、持久环境中。
这是不可能的。每当您调用
SetEnvX.exe
cmd.exe 都会生成一个子进程,该子进程从 cmd.exe 继承环境变量。
SetEnvX.exe
在其环境中设置环境变量,但完成后,它的环境块消失。所以父 cmd.exe 不会从子进程获取任何变量 SetEnvX.exe
。
TL;博士:
子进程可以继承父进程的环境变量,但父进程退出时不能继承子进程的环境变量。
解决方法:
如果您自己编译
SetEnvX.exe
,则无需设置环境变量,您可以打印该值,然后在cmd.exe中捕获它。例如:
for /f "delims=" %%k in ('SetEnvX.exe') do set VARIABLE=%%k
每个进程在出生时都会继承其父进程的变量。您不能从孩子那里继承变量。虽然注册表中有一个“全局持久环境”,但它不是随机 CMD.EXE 进程中的环境。
注意,批处理文件是由CMD.EXE执行的,一般没有自己的进程。
在 Windows 7 下,我能够为批处理实用程序完成此操作,这些实用程序旨在通过使用 DLL 注入父进程来为其执行的进程(父进程)设置环境变量。然而,我所有使用此技术的批处理实用程序在 Windows 10 中都崩溃了。使用 for 命令并将 set 命令写入批处理文件并不总是解决方案,因为有时所需的环境变量内容是另一个命令的输出,而该命令是无法提前预测的存在命令行引用问题,这些问题很难(不可能?)通过编程解决。迫切需要更好的技术,因为内置的 set 和 for 命令极其有限。其中一些在 Windows XP 和之前的版本中要好得多,因为您实际上可以将命令的输出直接通过管道传输到 SET 命令中。然而,微软以其无限的智慧(不是!)选择在 Windows 7 及更高版本中删除该功能(不确定 Vista 是否如此)。