简体   繁体   English

如何在PowerShell中更改环境变量并启动应用程序

[英]How to change a environment variable in PowerShell and launch an application

In PowerShell, I need to change the system path variable: 在PowerShell中,我需要更改系统路径变量:

$oldPath = [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
[System.Environment]::SetEnvironmentVariable('Path', (Transform-It $oldPath), 'Machine')

And then launch a program: 然后启动一个程序:

& $someExeName 'someargument'

The problem I am getting is that the executable is using the old environment. 我得到的问题是可执行文件正在使用旧环境。 It doesn't recognize the new path. 它无法识别新路径。 If I also change $env.path , to change the path only for this PowerShell session, it also does not propagate to the new process. 如果我还更改$env.path ,要仅更改此PowerShell会话的路径,它也不会传播到新进程。 If I close PowerShell and launch the executable in a new window, it's fine. 如果我关闭PowerShell并在新窗口中启动可执行文件,那很好。 Presumably it's inheriting the (non-updated) environment from the PowerShell process. 据推测,它继承了PowerShell流程中的(未更新的)环境。

What is the best practice for changing an environment variable in PowerShell, and having it recognized by new processes launched from that window? 在PowerShell中更改环境变量并通过从该窗口启动的新进程识别它的最佳实践是什么?

In general, child processes inherit the environment from the parent process*. 通常,子进程从父进程*继承环境。 If you spawn a new PowerShell session from an existing PowerShell session, the new session will inherit the environment variables from that session (but no other variables). 如果从现有PowerShell会话生成新的PowerShell会话,则新会话将从该会话继承环境变量(但不包含其他变量)。

However, the Path variable is an exception that causes a lot of confusion: Even though it's an environment variable, new PowerShell sessions read its value from the registry key HKLM:\\System\\CurrentControlSet\\Control\\Session Manager\\Environment , overriding the value inherited from a parent session. 但是, Path变量是一个异常,会引起很多混淆:即使它是一个环境变量,新的PowerShell会话也会从注册表项HKLM:\\System\\CurrentControlSet\\Control\\Session Manager\\Environment读取其值,从而覆盖继承的值来自父会话。

  • This behavior is specific to the Path variable. 此行为特定于Path变量。 Other environment variables are inherited from the parent session regardless of whether they were defined only in the parent session or are stored in the aforementioned registry key. 其他环境变量从父会话继承,无论它们是仅在父会话中定义还是存储在上述注册表项中。

  • This behavior is also specific to PowerShell. 此行为也特定于PowerShell。

    » If you change Path in a PowerShell session, but not in the registry, and spawn a new PowerShell session (eg with start powershell ), the new session will have the path from the registry, but if you spawn a cmd session, the new session will have the path from the PowerShell session that spawned it. »如果在PowerShell会话中更改路径但不在注册表中更改路径 ,并生成新的PowerShell会话(例如,使用start powershell ),则新会话将具有来自注册表的路径,但是如果您生成cmd会话,则新的会话将具有产生它的PowerShell会话的路径。

    » Likewise, if you change Path in a cmd session (with set Path=New Path ) and spawn a PowerShell session, the new session will have the path from the registry, but if you spawn a cmd session, it will have the changed path from the parent cmd session. »同样,如果在cmd会话中更改路径 (使用set Path=New Path )并生成PowerShell会话,则新会话将具有来自注册表的路径,但是如果您生成cmd会话,则它将具有更改的路径来自父cmd会话。

    » The default behavior is to inherit the path (along with the rest of the environment) from the parent process (as cmd does). »默认行为是从父进程继承路径(以及环境的其余部分)(如cmd所示)。 However, it's quite possible that some other programs behave in a similar fashion to PowerShell, overriding the inherited value with the registry value . 但是,很有可能其他一些程序的行为与PowerShell类似,用注册表值覆盖继承的值 This behavior is not common, but the possibility can't be ruled out that this happens with your executable. 这种行为并不常见,但不能排除可执行文件发生这种情况的可能性。

The following commands change Path in the current session, and not in the registry: 以下命令更改当前会话中的路径 ,而不是在注册表中:

$env:Path = 'New path'

[System.Environment]::SetEnvironmentVariable('Path', 'New Path', 'Process')


The following commands change Path in the registry, and not in the current session: 以下命令更改注册表中的Path ,而不是当前会话中的路径

Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name 'Path' -Value 'New Path'

[System.Environment]::SetEnvironmentVariable('Path', 'New Path', 'Machine')

What you're describing doesn't make sense to me, because you say that you've tried one method that changes the path in the registry, and one that changes the path in the PowerShell session, and that the executable you're spawning doesn't have the changed path either way. 您所描述的内容对我没有意义,因为您说您已经尝试过一种方法来更改注册表中的路径,一种更改PowerShell会话中的路径,以及您正在生成的可执行文件两种方式都没有改变的路径。 AFAIK the original environment isn't cached anywhere, and the child process has to be getting the path from either the parent process's environment or the registry. AFAIK原始环境不会缓存在任何地方,子进程必须从父进程的环境或注册表获取路径。

What I suggest it to make absolutely sure you've changed the path both ways before launching the executable: 我建议您确保在启动可执行文件之前已经双向改变了路径:

  1. Open a PowerShell session 打开PowerShell会话
  2. Change the path using one of the methods that changes it in the session 使用在会话中更改路径的方法之一更改路径
  3. Change the path using one of the methods that changes it in the registry 使用在注册表中更改它的方法之一更改路径
  4. Launch the executable 启动可执行文件

If for some inexplicable reason that doesn't work, try this: 如果由于某些无法解释的原因不起作用,请尝试以下方法:

  1. Open a PowerShell session 打开PowerShell会话
  2. Change the path using one of the methods that changes it in the registry 使用在注册表中更改它的方法之一更改路径
  3. Rather than launching the executable directly from that PowerShell session, execute this command 不是直接从该PowerShell会话启动可执行文件,而是执行此命令

     powershell "& $someExeName 'someargument'" 

    to have the executable launched by a new but non-interactive PowerShell session that will read the Path environment variable from the registry. 使用可从注册表中读取Path环境变量的新但非交互式PowerShell会话启动可执行文件。


* Note that the inheritance of the environment is the only relationship between parent and child processes in Windows. *请注意,环境的继承是Windows中父进程和子进程之间的唯一关系。 Other than that they're completely independent (there's no hierarchy as there is in Unix and Linux). 除此之外,它们完全独立(没有像Unix和Linux那样的层次结构)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Powershell中执行环境变量时如何传递参数? - How to pass arguments when executing environment variable in Powershell? 如何传播从Cygwin运行的Powershell的Windows环境变量 - How to propagate windows environment variable for powershell run from cygwin 如何在Powershell的同一会话上(立即)更新环境变量? - How to update environment variable on the same session (immediately) on powershell? 通过 Powershell 创建环境变量 - Creating Environment Variable Through Powershell Powershell 为局部变量设置环境变量 - Powershell Setting Environment variable for local variable 可以在“ Metro”环境和桌面环境中启动应用程序吗? -Windows 8 / 8.1 - Possible to launch an application in the “Metro” environment and desktop environment? - Windows 8/8.1 如何声明“ GOOGLE_APPLICATION_CREDENTIALS”环境变量? - How to declare the `GOOGLE_APPLICATION_CREDENTIALS` environment variable? 使用PowerShell设置嵌套的可扩展环境变量 - Set nested expandable environment variable with PowerShell 通过在cmd中设置环境变量在PowerShell中执行命令 - Executing a command in PowerShell by setting an environment variable in cmd PowerShell:仅为单个命令设置环境变量 - PowerShell: Setting an environment variable for a single command only
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM