如何从Powershell调用批处理脚本?

发布于 2024-10-06 17:45:10 字数 90 浏览 0 评论 0原文

我有一个大批处理脚本,它设置一堆环境变量。 我想从 powershell 调用该批处理脚本,这样我就可以同时受益于我的脚本和 powershell 设置的环境变量。

I have one big batch script which sets bunch of environment variables.
I want to call that batch script from powershell, that way I can get benefits of both i.e. enviorment variable set by my script and powershell.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

陈独秀 2024-10-13 17:45:10

如果您获取 PowerShell 社区扩展,其中有一个运行批处理文件的 Invoke-BatchFile 命令但更重要的是,它保留了批处理文件所做的任何环境变量修改,例如:

>Invoke-BatchFile 'C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat'
Setting environment for using Microsoft Visual Studio 2008 x86 tools.

If you grab the PowerShell Community Extensions, there is an Invoke-BatchFile command in it that runs the batch file but more importantly, it retains any environment variable modifications made by the batch file e.g.:

>Invoke-BatchFile 'C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat'
Setting environment for using Microsoft Visual Studio 2008 x86 tools.
葬心 2024-10-13 17:45:10

这个想法来自这篇博客文章:没有什么能解决所有问题 - 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"
}

PS 以下是向 PowerShell 添加类似功能的建议:将点采购概念扩展到 cmd 文件

The idea comes from this blog post: Nothing solves everything – PowerShell and other technologies

Here is my version of this script. It calls a batch file (or any native command) and propagates its environment:


UPDATE: Improved and better tested version of this script is here: 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"
}

P.S. Here is the proposal to add similar capability to PowerShell: Extend dot sourcing concept to cmd files

旧情别恋 2024-10-13 17:45:10

是否可以将批处理脚本转换为 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')

Is it possible to convert your batch script to PowerShell script? If you run the bat file, its is executed in separate session that doesn't modify PowerShell's env variables.

You can work with env variables very smoothly:

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

Or even (much shorter, returns only string):

PS> $env:path
c:\dev\CollabNet\Subversion Client;C:\Windows\system32;...

You can change the environment path like this:

PS> $env:path += ";c:\mydir"

And you can even set environment variables at machine level like this:

# fist arg = env variable name, second = value, third = level, available are 'Process', 'User', 'Machine'
PS> [Environment]::SetEnvironmentVariable('test', 'value', 'machine')
才能让你更想念 2024-10-13 17:45:10

@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

@Roman Kuzmin's solution works great, but piping the command output to nul can kind of leave you in the dark. So I made a few tweaks to allow for the command output to display normally, and instead pipe the env vars to a temp file to read in afterwards:

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
烟雨扶苏 2024-10-13 17:45:10

您只需输入名称即可从 Powershell 运行批处理脚本,但这对您没有帮助。批处理脚本中设置的环境变量仅在该批处理以及该批处理运行的任何内容中可见。一旦控制权返回到 Powershell,环境变量就消失了。不过,您可以让批处理脚本在最后运行 set ,然后将其输出解析到 PSH 环境变量中。

You can run a batch script from Powershell just by putting its name, but that won't help you. Environment variables set in the batch script will only be visible from that batch and anything that batch runs. Once the control returns back to Powershell the environment variables are gone. You could have the batch script run set at the end and then parse its output into your PSH environment variables, though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文