如何更改环境变量powershell并启动应用程序 [英] How to change environment variable powershell and launch an application

查看:636
本文介绍了如何更改环境变量powershell并启动应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在PowerShell中,我需要更改系统路径变量:

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

然后启动一个程序:

 & $ someExeName'someargument'

我遇到的问题是可执行文件正在使用旧的环境。它不认识新路。如果我也更改$ env.path,为了更改此PowerShell会话的路径,它也不会传播到新进程。如果我关闭PowerShell,并在新窗口中启动可执行文件,这很好。大概是从PowerShell进程继承(未更新)的环境



在PowerShell中更改环境变量的最佳做法是什么,并让新进程识别出来从那个窗口开始?

解决方案

一般来说,子进程从父进程继承环境* 。如果从现有PowerShell会话中生成新的PowerShell会话,则新会话将从该会话继承环境变量(但不包含其他变量)。



但是,路径变量是一个异常,导致很多混乱:即使它是一个环境变量,新的PowerShell会话读取其值从注册表项 HKLM:\System\CurrentControlSet\Control\Session Manager\Environment ,覆盖从父会话继承的值。




  • 此行为特定于路径变量。无论它们是仅在父会话中定义还是存储在上述注册表项中,其他环境变量都将从父会话继承。


  • 此行为是也具体到PowerShell。



    »如果您在PowerShell会话中更改路径,而不是在注册表中更改,并生成新的PowerShell会话(例如,使用 start powershell ),则新的会话将具有从注册表的路径,但是如果您生成cmd会话,则新会话将具有从PowerShell会话生成的路径。



    »同样,如果在cmd会话中更改路径(使用设置Path = New Path )并生成PowerShell会话,则新会话将具有路径从注册表,但如果您生成一个cmd会话,它将从父cmd会话更改路径。



    »默认行为是从父进程继承路径(以及其他环境)(如cmd所示)。然而,很可能某些其他程序的行为与PowerShell类似,用注册表值覆盖继承的值。这种行为是不常见的,但不能排除这种可执行文件的可能性。




以下命令在当前会话中更改路径,而不是在注册表中更改:

  $ env:Path ='新路径'

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



以下命令在注册表中更改路径,而不是在当前会话:

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

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

你所描述的内容对我来说没有意义,因为你说你已经尝试过一种改变注册表中路径的方法, PowerShell会话,您生成的可执行文件的方式也不会改变。 AFAIK原始环境没有在任何地方缓存,子进程具有从父进程的环境或注册表获取路径。



我建议,确保你在启动可执行文件之前改变了路径:


  1. 打开PowerShell会话

  2. 使用在会话中更改它的方法之一更改路径

  3. 使用在注册表中更改它的方法之一更改路径/ li>
  4. 启动可执行文件

如果某些莫名其妙的原因无效,请尝试:


  1. 打开PowerShell会话

  2. 使用其中的一种方法更改路径注册表

  3. 而不是直接从该PowerShell会话启动可执行文件,执行此命令

      POW ershell& $ someExeName'someargument'

    让可执行文件由新的但非交互式的PowerShell会话启动,将从注册表中读取路径环境变量。







*请注意,环境的继承是Windows中父进程和子进程之间的唯一关系,除此之外,它们完全独立(没有层次结构,因为在Unix和Linux中)


In PowerShell, I need to change the system path variable:

$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. If I close PowerShell and launch the executable in a new window, it's fine. Presumably it's inheriting the (non-updated) environment from the PowerShell process

What is the best practice for changing an environment variable in PowerShell, and having it recognized by new processes launched from that window?

解决方案

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).

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.

  • This behavior is specific to the Path variable. 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.

    » If you change Path in a PowerShell session, but not in the registry, and spawn a new PowerShell session (e.g. 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.

    » 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.

    » The default behavior is to inherit the path (along with the rest of the environment) from the parent process (as cmd does). However, it's quite possible that some other programs behave in a similar fashion to PowerShell, overriding the inherited value with the registry value. 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:

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. 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.

What I suggest it to make absolutely sure you've changed the path both ways before launching the executable:

  1. Open a PowerShell session
  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
  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 "& $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.


* Note that the inheritance of the environment is the only relationship between parent and child processes in Windows. Other than that they're completely independent (there's no hierarchy as there is in Unix and Linux).

这篇关于如何更改环境变量powershell并启动应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆