可执行文件如何在父 CMD 或批处理上下文中设置环境变量?

Posted

技术标签:

【中文标题】可执行文件如何在父 CMD 或批处理上下文中设置环境变量?【英文标题】:How can an executable set an environment variable in the parent CMD or batch context? 【发布时间】:2017-09-15 19:14:13 【问题描述】:

我有一个设置环境变量的 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 是否创建一个新环境然后退出该环境,比如 SETLOCAL ENDLOCAL? 【参考方案1】:

这是不可能的。每当您调用SetEnvX.exe cmd.exe 时,都会生成一个从 cmd.exe 继承环境变量的子进程。

SetEnvX.exe 在其环境中设置环境变量,但当它完成时,它的环境块消失。所以父 cmd.exe 不会从子 SetEnvX.exe 获取任何变量。

TL;DR:

子进程可以继承父进程的环境变量,但父进程退出时不能继承子进程的环境变量。

解决方法:

如果你自己编译SetEnvX.exe,不用设置环境变量,你可以打印值,然后在cmd.exe中捕获。例如:

for /f "delims=" %%k in ('SetEnvX.exe') do set VARIABLE=%%k

【讨论】:

从技术上讲,(有时)可以打开父进程并重写其环境块,但这是不可取的,也是糟糕的设计。您需要一种协作设计,例如将新变量写入标准输出的解决方法。 请注意,环境变量是 Unicode,for /f 使用控制台的当前输出代码页从管道中逐行解码。一般来说,您可能需要通过将控制台设置为代码页 65001 (UTF-8) 并让 SetEnvX.exe 将 UTF-8 写入标准输出来进行更多合作。 cmd /k "set a=b" 在你的 cmd 文件中将在返回时将a 设置为当前命令行。【参考方案2】:

每个进程在出生时都会继承其父进程的变量。您不能从孩子那里继承变量。虽然注册表中有一个“全局持久环境”,但不是随机 CMD.EXE 进程中的环境。

注意批处理文件是由CMD.EXE执行的,一般没有自己的进程。

【讨论】:

以上是关于可执行文件如何在父 CMD 或批处理上下文中设置环境变量?的主要内容,如果未能解决你的问题,请参考以下文章

Java环境变量设置成功后运行cmd时提示错误 不是内部或外部命令,也不是可运行的程序或批处理文件

windows7 64bit下mvn命令后提示‘cmd’不是内部或外部命令,也不是可执行程序或批处理文件

运行cmd后,arp-a显示:不是内部或外部命令,也不是可运行的程序或批处理程序。怎么办?

cmd窗口输入code打不开vscode。提示不是内部或外部命令,也不是可运行的程序或批处理文件?

cmd 中连接mysql时报'mysql'不是内部或外部命令,也不是可运行的程序或批处理文件,该怎么办?

CMD下输入python依然是提示不是内部或外部命令,也不是可运行的程序或批处理文件