I need to setup a PowerShell script based upon a batch script. The original batch script looks like the following:
call %SYSTEMROOT%\setup_Env.BAT
command_name command_arguments
The command is dependent upon the environmental variables from the setup_ENV.BAT
being setup.
$tempFile = [IO.Path]::GetTempFileName()
$script = "%SYSTEMROOT%\setup_Env.BAT"
cmd /c " $script && set > $tempFile "
cmd /c " command_name command_arguments"
I received the error:
cmd : 'command_name is not recognized as an internal or external command,...
If there is a better way to do this in PowerShell, I am open to it.
You need to pass a single command line to cmd
to make this work:
cmd /c "call %SYSTEMROOT%\setup_Env.BAT && command_name command_arguments"
As Ansgar Wiechers points out, every cmd
invocation runs in a child process, and any environment modifications made in a child process are not visible to the calling process and therefore also not to future child processes.
By contrast, in the single command line above, the environment-variable modifications performed by setup_Env.BAT
are visible to command_name
by the time it executes.
Caveat: If command_arguments
contains %...%
-style references to the environment variables defined in setup_Env.BAT
, more work is needed:
%...%
-style references to !...!
-style references.Additionally invoke cmd
with /v
to enable delayed variable expansion (the equivalent of setlocal enabledelayedexpansion
inside a script`:
cmd /v /c "call %SYSTEMROOT%\setup_Env.BAT && command_name args_with_delayed_var_refs"
Caveat: The above may still not work as intended if command_arguments
happens to contain !
chars. that should be treated as literals (and/or command_name
is another batch file containing such).
In that event, the simplest approach is to simply recreate the entire batch file in a temporary file and invoke that:
# Get temp. file path
$tempBatFile = [IO.Path]::GetTempFileName() + '.bat'
# Write the content of the temp. batch file
@'
@echo off
call %SYSTEMROOT%\setup_Env.BAT
command_name command_arguments
'@ | Set-Content $tempBatFile
# Execute it.
& $tempBatFile
# Clean up.
Remove-Item -LiteralPath $tempBatFile