【问题标题】:Add environment variables with PowerShell and bat files使用 PowerShell 和 bat 文件添加环境变量
【发布时间】:2020-11-04 14:27:15
【问题描述】:

作为项目的一部分,我需要使用 PowerShell 脚本运行两个 bat 文件。这些 bat 文件将执行多项操作,包括创建环境变量。 但是问题。创建了第一个环境变量(使用第一个 bat 文件创建的那些),但没有创建第二个环境变量(必须在执行第二个 bat 文件时创建)。第二个的执行“很好”,因为它必须执行的其余操作都做得很好。

我使用相同的函数来执行这些 .bat 文件。

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
$argList = "/c '"$batFile'""
$process = Start-Process "cmd.exe" -ArgumentList $argList -Wait -PassThru -Verb runAd
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")

我用这条线 $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") 重新加载环境变量。但这并没有解决问题。如果没有这一行,我就有了与正在创建的第二个 bat 文件(运行的第二个)相对应的环境变量。有了它,我只有第一个。

我还注意到,如果我重新运行我的 PowerShell 程序(所以重新运行批处理文件),我已经创建了所有环境变量。

【问题讨论】:

    标签: powershell batch-file environment-variables


    【解决方案1】:

    第一关:

    看起来您在执行第二个批处理文件的代码中有错误,所以我怀疑您重新编写了代码到这里并且它根本不是原始形式,因为它的编写方式您永远不会得到任何东西进一步。

    你知道什么 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 是您当前环境的路径,这包括来自 Systemcurrentuser 配置文件(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>
    

    但这并不是真正发生的事情,您似乎正在将命令环境更新回本地计算机

    【讨论】:

      猜你喜欢
      • 2012-11-27
      • 1970-01-01
      • 2014-04-16
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      相关资源
      最近更新 更多