web-dev-qa-db-ja.com

Powershellからバッチスクリプトを呼び出す方法

一連の環境変数を設定する1つの大きなバッチスクリプトがあります。そのバッチスクリプトをpowershellから呼び出したいので、スクリプトとpowershellによって設定された環境変数の両方の利点を得ることができます。

23
Invincible

アイデアはこのブログ投稿から来ています: 何も解決しないもの– PowerShellと他のテクノロジー

これがこのスクリプトの私のバージョンです。バッチファイル(または任意のnativeコマンド)を呼び出し、その環境を伝播します。


更新:このスクリプトの改良され、よりよくテストされたバージョンは次のとおりです: 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ファイルに拡張

12
Roman Kuzmin

PowerShell Community Extensions を取得すると、バッチファイルを実行する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.
22
Keith Hill

バッチスクリプトを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')
2
stej

名前を入力するだけでPowershellからバッチスクリプトを実行できますが、これは役に立ちません。バッチスクリプトで設定された環境変数は、そのバッチおよびバッチで実行されるものからのみ表示されます。コントロールがPowershellに戻ると、環境変数はなくなります。ただし、最後にsetを実行するバッチスクリプトを実行し、その出力をPSH環境変数に解析することもできます。

0
Gabe

@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
0
Dennis George