我有一个设置多个环境变量的批处理脚本。我想从PowerShell中调用该批处理脚本,这样我就可以同时享受两者的好处,即我的脚本设置的环境变量和PowerShell。
我有一个设置多个环境变量的批处理脚本。我想从PowerShell中调用该批处理脚本,这样我就可以同时享受两者的好处,即我的脚本设置的环境变量和PowerShell。
>Invoke-BatchFile 'C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat'
Setting environment for using Microsoft Visual Studio 2008 x86 tools.
这个想法来自于这篇博客文章:“没有一种方法可以解决所有问题” - PowerShell和其他技术
这是我的版本脚本。它调用一个批处理文件(或任何本地命令)并传播其环境:
更新:此脚本的改进并且经过了更好的测试,可以在这里找到:Invoke-Environment.ps1
<#
.SYNOPSIS
Invokes a command and imports its environment variables.
.DESCRIPTION
It invokes any cmd shell command (normally a configuration batch file) and
imports its environment variables to the calling process. Command output is
discarded completely. It fails if the command exit code is not 0. To ignore
the exit code use the 'call' command.
.PARAMETER Command
Any cmd shell command, normally a configuration batch file.
.EXAMPLE
# Invokes Config.bat in the current directory or the system path
Invoke-Environment Config.bat
.EXAMPLE
# Visual Studio environment: works even if exit code is not 0
Invoke-Environment 'call "%VS100COMNTOOLS%\vsvars32.bat"'
.EXAMPLE
# This command fails if vsvars32.bat exit code is not 0
Invoke-Environment '"%VS100COMNTOOLS%\vsvars32.bat"'
#>
param
(
[Parameter(Mandatory=$true)] [string]
$Command
)
cmd /c "$Command > nul 2>&1 && set" | .{process{
if ($_ -match '^([^=]+)=(.*)') {
[System.Environment]::SetEnvironmentVariable($matches[1], $matches[2])
}
}}
if ($LASTEXITCODE) {
throw "Command '$Command': exit code: $LASTEXITCODE"
}
补充一下,这里有一个提案希望将类似的功能添加到PowerShell中:将点运算符概念扩展到cmd文件
$Command > nul 2>&1 && set
。 - Joey您是否可以将批处理脚本转换为PowerShell脚本?如果运行bat文件,则在单独的会话中执行它,不会修改PowerShell的环境变量。
您可以非常顺畅地使用环境变量:
PS> Get-ChildItem env:
Name Value
---- -----
ALLUSERSPROFILE C:\ProgramData
APPDATA C:\Users\xyz\AppData\Roaming
CommonProgramFiles C:\Program Files (x86)\Common Files
CommonProgramFiles(x86) C:\Program Files (x86)\Common Files
CommonProgramW6432 C:\Program Files\Common Files
COMPUTERNAME xyz
ComSpec C:\Windows\system32\cmd.exe
DXSDK_DIR D:\prgs\dev\Microsoft DirectX SDK (August 2009)\
FP_NO_HOST_CHECK NO
HOMEDRIVE Z:
HOMEPATH \
...
PS> Get-Item env:path
Name Value
---- -----
Path c:\dev\CollabNet\SubversionClient;C:\Windows\system32;...
PS> $env:path
c:\dev\CollabNet\Subversion Client;C:\Windows\system32;...
PS> $env:path += ";c:\mydir"
# fist arg = env variable name, second = value, third = level, available are 'Process', 'User', 'Machine'
PS> [Environment]::SetEnvironmentVariable('test', 'value', 'machine')
@Roman Kuzmin的解决方案非常好,但是将命令输出重定向到nul可能会让你感到困惑。因此,我进行了一些调整,允许命令输出正常显示,并将环境变量重定向到临时文件中以便之后读取:
param
(
[Parameter(Mandatory=$true)] [string]
$Command
)
$VarsPath = [IO.Path]::GetTempFileName()
cmd /c "$Command && set > $VarsPath"
if (-not $LASTEXITCODE) {
Get-Content $VarsPath | ForEach-Object {
if ($_ -match '^([^=]+)=(.*)') {
[System.Environment]::SetEnvironmentVariable($matches[1], $matches[2])
}
}
}
Remove-Item $VarsPath
你可以通过在PowerShell中输入批处理文件的名称来运行它,但这并没有什么帮助。在批处理脚本中设置的环境变量只能从该批处理和该批处理运行的任何内容中可见。一旦控制返回到PowerShell,环境变量就会消失。不过,你可以让批处理脚本在结尾处运行set
命令,然后将其输出解析为PSH环境变量。