Run a .cmd file through PowerShell

Learn run a .cmd file through powershell with practical examples, diagrams, and best practices. Covers windows, powershell, cmd development techniques with visual explanations.

Executing .cmd Files from PowerShell: A Comprehensive Guide

Hero image for Run a .cmd file through PowerShell

Learn various methods to run legacy .cmd batch files within PowerShell, understanding their nuances and best practices for seamless integration.

PowerShell is a powerful, modern scripting environment for Windows, but often you'll encounter legacy batch scripts (.cmd or .bat) that you need to execute. Directly running a .cmd file from PowerShell isn't always as straightforward as typing its name. This article explores the different ways to invoke .cmd files, explaining the underlying mechanisms and providing practical examples to help you integrate your old scripts into new PowerShell workflows.

Understanding the Challenge

When you type a command like my_script.cmd directly into PowerShell, PowerShell tries to interpret it. Since .cmd files are designed for cmd.exe, PowerShell's default behavior might not execute them as expected. This often leads to errors or the script not running at all. The key is to tell PowerShell to hand off the execution to cmd.exe.

flowchart TD
    A[PowerShell Invocation] --> B{Is it a native PowerShell command?}
    B -->|Yes| C[Execute directly in PowerShell]
    B -->|No| D{Is it an executable (.exe)?}
    D -->|Yes| E[Execute directly]
    D -->|No| F{Is it a script (.ps1, .cmd, .bat)?}
    F -->|Yes| G{Check file extension and PATHEXT}
    G -->|PowerShell Script| C
    G -->|CMD/BAT Script| H["Requires explicit cmd.exe invocation"]
    H --> I[Execute via `cmd.exe /c`]

PowerShell Command Execution Flow

Method 1: Using cmd.exe /c

The most robust and recommended way to run a .cmd file from PowerShell is to explicitly invoke cmd.exe and pass the .cmd file as an argument using the /c switch. The /c switch tells cmd.exe to execute the command string and then terminate.

cmd.exe /c "C:\Path\To\Your\script.cmd"

# Or, if the script is in the current directory:
cmd.exe /c ".\script.cmd"

# Passing arguments to the .cmd script:
cmd.exe /c "C:\Path\To\Your\script.cmd" Arg1 "Argument with spaces"

Executing a .cmd file using cmd.exe /c

Method 2: Using the Call Operator &

The call operator (&) in PowerShell allows you to run commands, scripts, or executables that are stored in a string or a variable. While it can sometimes work for .cmd files, it's less reliable than cmd.exe /c because PowerShell still tries to interpret the command before passing it. However, for simple .cmd files without complex internal logic, it might suffice.

& "C:\Path\To\Your\script.cmd"

# Or, if the script is in the current directory:
& ".\script.cmd"

# Passing arguments:
& "C:\Path\To\Your\script.cmd" Arg1 "Argument with spaces"

Executing a .cmd file using the call operator &

Method 3: Using Start-Process

Start-Process is a PowerShell cmdlet designed to start new processes. It's useful when you want to run the .cmd file in a new window, or if you need more control over the process's execution, such as waiting for it to complete or capturing its output.

# Run in a new window, without waiting:
Start-Process -FilePath "C:\Path\To\Your\script.cmd"

# Run and wait for the process to complete:
Start-Process -FilePath "C:\Path\To\Your\script.cmd" -Wait

# Run and pass arguments:
Start-Process -FilePath "C:\Path\To\Your\script.cmd" -ArgumentList "Arg1", "Argument with spaces"

# Run hidden and wait:
Start-Process -FilePath "C:\Path\To\Your\script.cmd" -WindowStyle Hidden -Wait

Executing a .cmd file using Start-Process

Capturing Output and Exit Codes

When running .cmd files, especially in automated scripts, you often need to capture their output (stdout/stderr) and check their exit code to determine success or failure. This is crucial for error handling and logging.

# Using cmd.exe /c to capture output and exit code
$command = "C:\Path\To\Your\script.cmd Arg1"
$output = cmd.exe /c $command
$exitCode = $LASTEXITCODE

Write-Host "Output:"
$output
Write-Host "Exit Code: $exitCode"

# Using Start-Process to capture output (requires redirection)
# This is more complex as Start-Process runs in a separate process
# For simple output capture, cmd.exe /c is often easier.
# Example: Redirecting output to a file
Start-Process -FilePath "C:\Path\To\Your\script.cmd" -ArgumentList "Arg1" -RedirectStandardOutput "output.txt" -Wait
$fileContent = Get-Content "output.txt"
Write-Host "File Content: $fileContent"

Capturing output and exit codes from .cmd execution