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

- 432
- 4
- 12

- 194,368
- 42
- 353
- 369
-
Notes to self, as per below, 1.To install from the zip file on codeplex, right-click and a modal button, "unblock" appears; click it. 2.Unzip after unblocking and then place the folder in your modules location, as per $PSHome\Modules. http://stam.blogs.com/8bits/2010/06/installing-powershell-community-extensions.html – AnneTheAgile Aug 24 '12 at 18:46
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

- 40,627
- 11
- 95
- 117
-
1You may want to use just `$Command > nul 2>&1 && set` just in case `$Command` has a non-zero exit code but still changes the environment. – Joey Dec 09 '10 at 23:02
-
The linked 'improved and better tested' version didn't work for me, but copy pasting the script from this answer did. – Scott Langham Aug 21 '14 at 11:00
-
Thank you for the alarm. Can you create an issue [there](https://github.com/nightroman/PowerShelf/issues) and describe your use case? – Roman Kuzmin Aug 21 '14 at 11:09
-
I haven't got an account there. I tried: Invoke-Environment '"%VS120COMNTOOLS%\vsvars32.bat"' -Force – Scott Langham Aug 21 '14 at 11:44
-
Fixed (weird, cmd needs one extra space after /c). I cannot try with VS120COMNTOOLS now but with VS100COMNTOOLS it works fine. – Roman Kuzmin Aug 23 '14 at 04:28
-
so... if the batch file calls/runs other batch files, or if it branches and only sets certain environment variables depending on certain conditions, then this is not a complete solution and might miss or set values inappropriately? not complaining per se, just trying to verify my understanding of what it's doing – Code Jockey Jul 23 '15 at 12:39
-
I'll add the security warning not to curl/wget anything from a public Git repo. Download the script and host it in a trusted place. – Exegesis Apr 23 '21 at 16:35
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')

- 28,745
- 11
- 71
- 104
@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

- 1,495
- 2
- 10
- 18
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.

- 84,912
- 12
- 139
- 238