第一关:
看起来您在执行第二个批处理文件的代码中有错误,所以我怀疑您重新编写了代码到这里并且它根本不是原始形式,因为它的编写方式您永远不会得到任何东西进一步。
你知道什么 TL;DR:试试这个
我已经写了很多,考虑到代码的 sn-p 还不够,这是一个兔子洞,代码显然是重写的,因为它引入了一个明显不同的错误,你的描述离开了需要的东西。
我将重新排序下面的其他一些要点,您可以随意阅读/忽略任何内容。
但这里,是长和短。
如果您需要运行此 CMD 脚本,并从中获取一些内容以添加到路径,请让它们正常运行并将 echo path 他们创建到标准输出中,然后将其捕获到 powershell 变量中,重复数据删除它在 powershell 中并直接为您现有的 powershell 环境设置路径。
修改您的两个 CMD Scripts AKA Batch Files 以将其添加到任何现有行之前的最顶部。
@(SETLOCAL
ECHO OFF )
CALL :ORIGINAL_SCRIPT_STARTS_HERE >NUL 2>NUL
ECHO=%PATH%
( ENDLOCAL
EXIT /B )
:ORIGINAL_SCRIPT_STARTS_HERE
REM All your original script lines should be present below this line!!
PowerShell代码基本上会
$batfile_1 = "C:\Admin\SE\Batfile_1.cmd"
$batfile_2 = "C:\Admin\SE\Batfile_2.cmd"
$Path_New = $($env:path) -split ";" | select -unique
$Path_New += $(&$batFile_1) -split ";" | ? {$_ -notin $Path_New}
$Path_New += $(&$batFile_2) -split ";" | ? {$_ -notin $Path_New}
$env:path = $($Path_New | select -unique) -join ";"
虽然如果您不需要单独的可测试步骤,您可以使其更简洁:
$batfile_1 = "C:\Admin\SE\Batfile_1.cmd"
$batfile_2 = "C:\Admin\SE\Batfile_2.cmd"
$env:path = $(
$( $env:path
&$batFile_1
&$batFile_2
) -split ";" | select -unique
) -join ";"
好的,留下大部分完成的东西,我停下来尝试修改我的观点,因为我跟随兔子洞跟踪碎片,因为它会在这里的某些方面提供一些启示
第二关:你不需要start-process来运行CMD脚本,你可以在本地运行一个cmd脚本,它会自动实例化一个cmd实例。
Start-Process 肯定会将它作为一个单独的进程生成,但是您等待它,尽管您使用 -PassThru 并将其保存为变量,但您无需对其进行任何操作来尝试检查其状态或错误代码,因此您也可以直接运行 CMD 脚本并在您的 powershell 窗口中查看它的 StdOut,或者将其保存在变量中以在需要时记录它。
第三关:为什么不直接使用 Powershell 设置环境变量?
我猜这些脚本会做其他事情,但可能是您应该将他们想要设置的路径回显到 PowerShell 脚本,然后对其进行重复数据删除并在完成后设置路径。
第 4 关:$env:Path 是您当前环境的路径,这包括来自 System 和 currentuser 配置文件(HKLM:和 HKCU:环境的注册表项)的所有路径文本,而 $( [System.Environment]::GetEnvironmentVariable("Path","Machine") ) 是您的System(本地机器)pat 已从您的注册表中派生。
第 5 关:操作环境特定于每个 shell,当您启动 CMD /c 的新实例时,它会继承之前生成它的 cmd 实例的环境。
第 6 关:对环境变量所做的更改不会“持续”,即:您无法打开新的 CMD / Powershell 实例并查看它们,一旦您关闭原来的 cmd 窗口,它们就会消失了,除非您编辑这些项目的注册表值directoy 或在cmd 会话中使用SET X(这是有问题的,应该避免!)并且也只会影响用户变量而不是system/local machine 变量.
因此,对一个 CMD 实例中的环境所做的任何更改都只能在现有的 shell 中运行,除非它们是在注册表中持久存在的更改,在这种情况下,它们只会影响启动的新 shell。
第 7 关:当你启动 powershell 时,它是一个运行 powershell 的 cmd shell,因此当解释器启动时,powershell 会继承本地机器和当前用户的变量。这将是 $env:xxx 中的内容
第 8 关:设置 $env:Path = $([System.Environment]::GetEnvironmentVariable("Path","Machine")) 将始终将当前的 powershell 环境更改为存储在环境变量的 [HKLM:\] 注册表项中的任何内容。
现在我们没有你的所有代码,只有正在发生的事情的描述。
看来你有一个脚本让我们称之为batFile_1.cmd,它正在你的中设置一些变量
对于您运行的每个批处理文件,无论是隐式生成还是显式生成,您都将继承前一个 shell 的命令环境。
然而
您使用其中的批处理文件生成的每个 CMD 实例都会生成一个单独的 cmd shell 实例,并且 CMD 的实例在其中运行,powershell.exe 正在其中运行,因此您的脚本正在其中运行。
现在我只是假设发生了什么,因为您只给出了一个小的 sn-p,这不足以真正重现您的实际问题。
但看起来你生成了一个 cmd 脚本,
因此,如果没有完整的上下文而不是 sn-p,很难确切地知道正在发生的事情,尽管我将在下面讨论一种可能发生的情况。
关于每个 CMD 实例的注释仅继承其父级的值。
(我觉得这在打开一个实际的 CMD 窗口并通过生成另一个 CMD 实例来测试 shell 的工作原理时更清楚。
当新实例退出时,变量会恢复到前一个实例,因为它们只会从父级移动到子级)
例如:
C:\WINDOWS\system32>set "a=hello"
C:\WINDOWS\system32>echo=%a%
hello
C:\WINDOWS\system32>CMD /V
Microsoft Windows [Version 10.0.18362.1082]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\WINDOWS\system32>(SET "a= there!"
More? SET "b=%a%!a!"
More? )
C:\WINDOWS\system32>echo=%b%
hello there!
C:\WINDOWS\system32>echo=%a%
there!
C:\WINDOWS\system32>exit
C:\WINDOWS\system32>echo=%a%
hello
C:\WINDOWS\system32>echo=%b%
%b%
C:\WINDOWS\system32>
但这并不是真正发生的事情,您似乎正在将命令环境更新回本地计算机