Can we call Bat command within powershell without calling/invoking a bat file?
For example bat script:
@echo [off]
echo sample batch script
pause
In powershell itself
Commands must be executed.
Can we call Bat command within powershell without calling/invoking a bat file?
For example bat script:
@echo [off]
echo sample batch script
pause
In powershell itself
Commands must be executed.
You can emulate most things BATCH.
PAUSE
.ECHO
is similar to Write-Host
and $Var | Out-Host
.Also, you can call BATCH commands with cmd.exe --% /c
, BUT, as soon as cmd.exe exits, the environment the command was executed in is gone - along with any environment variables that were set.
On the other hand, cmd.exe
's output can be saved to a variable.
In this example:
dir
is dynamically provided by first setting an environment variable $Env:DirPath = 'C:\Users\public'
, and then retrieved the environment variable in BATCH %DirPath%
.$Var = $(<code>)
to save output in $Var.NOTE: The closing parentheses is NOT at the end of the cmd.exe --%
line, because, if it was, it would be ignored by PowerShell.
$Env:DirPath = 'C:\Users\public'
$Var = $(
cmd.exe --% /c dir "%DirPath%" /w
)
$Var
You should also be able to use &
in the cmd.exe --%
command to execute more than one BATCH command, but I haven't experimented with that, so not sure how that would work out.
You cannot execute batch-file commands directly in PowerShell, because PowerShell doesn't understand them.
cmd.exe
(the interpreter of batch files) and PowerShell, by way of PowerShell providing aliases for its differently named commands (e.g., dir
for Get-ChildItem
), calls to these few commands only work the same in all but the simplest cases, given that PowerShell's parameter syntax differs fundamentally from that of cmd.exe
You can execute batch-file commands via cmd.exe
's CLI, namely either via cmd /c
(run cmd /?
for details) or by piping commands to cmd.exe
(... | cmd
), but note the following:
Like batch files, such calls run in a child process, so that modifications to environment variables wouldn't be seen by the caller, for instances.
The commands are interpreted as in interactive cmd.exe
sessions, which notably means that for
loops must use %i
rather than %%i
, for instance.
Passing multiple batch-file commands has severe limitations:
With cmd /c
, you can only pass a single line (any additional lines are ignored), so you must use cmd.exe
's &
operator to sequence multiple commands, which only works if these commands do not depend on each other with respect to variables.
# OK - the two commands aren't interdependent.
cmd /c 'ver & date /t'
# !! NOT OK - the %FOO% value isn't seen by the echo call
cmd /c '(Set FOO=bar) & echo %FOO%'
However, you can enable the delayed-variable-expansion feature via the /v
option, in which case using !...!
instead of %...%
does work:
# OK - thanks to /v and !FOO!
cmd /v /c '(Set FOO=bar) & echo !FOO!'
Separately, you can use an expandable (double-quoted) string ("..."
) in order to embed the value of PowerShell variables in the cmd /c
call, as an alternative to the --%
technique shown in Darin's answer; if you need to embed "
characters, escape them as `"
(or ""
):
$foo = 'bar' # define a PowerShell variable
cmd /c "echo $foo" # embed its value in the "..." string
With multiline pipeline input:
Even if you start your multiline input string with @echo off
, you will invariably see cmd.exe
's startup banner ( Microsoft Windows [Version ...]
) and one prompt string (e.g, C:\>
), and the source code line of each command will print either way before the result of its execution.
Unless the code exits with an explicit exit
call, the cmd.exe
's exit code will not reflect the exit code of the last command executed.
For more information as well as a helper function that creates a temporary batch file behind the scenes to avoid these limitations, see this answer
Here's an example that uses a here-string to feed multiple commands to cmd.exe
; as noted, you'll see the startup banner and one prompt string, and the source-code lines will print before each command's output:
@'
@echo off
ver
date /t
Set FOO=bar
echo %FOO%
exit
'@ | cmd.exe