How to call batch script from Powershell?
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.
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
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:\ProgramDataAPPDATA C:\Users\xyz\AppData\RoamingCommonProgramFiles C:\Program Files (x86)\Common FilesCommonProgramFiles(x86) C:\Program Files (x86)\Common FilesCommonProgramW6432 C:\Program Files\Common FilesCOMPUTERNAME xyzComSpec C:\Windows\system32\cmd.exeDXSDK_DIR D:\prgs\dev\Microsoft DirectX SDK (August 2009)\FP_NO_HOST_CHECK NOHOMEDRIVE Z:HOMEPATH \...PS> Get-Item env:pathName Value---- -----Path c:\dev\CollabNet\SubversionClient;C:\Windows\system32;...
Or even (much shorter, returns only string):
PS> $env:pathc:\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')