Windows Command Processor extensions, part 3
A flexible extension system for one of the oldest Windows applications
Published in Articles on by Michiel van Oosterhout ~ 3 min read
Part 1 of this series on extending Windows Command Processor used AutoRun to ensure our extension system can be initialized, but left the implementation for later, because we first needed to decide how to extend Windows Command Processor. Part 2 explored the use of functions as an extension mechanism. This part 3 of the series uses console aliases to further extend Windows Command Processor.

Commando: a Windows Command Line extension system
WordPerfect was one of the most successful word processors for MS-DOS in the late 80s. One of its most powerful features was its support for macros, recorded sequences of keyboard input that could be assigned to any key desired. Console Window Host actually supports a similar feature which we can use as an extension mechanism for Windows Command Processor.
Console aliases
Console Window Host supports console aliases, mappings from one string to another string. Also known as macros, they can be recorded using the doskey
command-line program. For example, if you often run cd %USERPROFILE%
, then you can use doskey
to record a home
macro and run that instead: doskey home=cd %USERPROFILE%
. To remove the macro run doskey home=
.
Macros can be used to intercept built-in commands as well as command-line programs. For example, recording cd=pushd $*
intercepts the cd
command and executes pushd
instead. Extensions can define macros in a macro file, a plain text file that contains one line for each macro that should be recorded, e.g. home=cd %USERPROFILE%
.
The Windows PowerShell script below creates a simple PushDir extension that defines 2 macros:
# Define the macros
$macros = @{
cd = "pushd $*"
chdir = "pushd $*"
}
# Ensure the extension's directory exists
$path = "$Env:LOCALAPPDATA\Commando\PushDir"
$_ = New-Item $path -Force -ItemType Directory
# Create the macro file
$lines = $macros.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }
Set-Content -Path "$path\macros.txt" -Value ([string]::Join("`r`n", $lines))
The doskey /macrofile=%LOCALAPPDATA%\Commando\PushDir\macros.txt
command will record PushDir's macros, after which the cd
and chdir
commands are effectively replaced with the pushd
command.
Functions
In part 2 of this series we explored the use of functions as an extension mechanism, which would require each extension to be added to the %PATH%
environment variable, which would not allow multiple extensions to export a function with the same name.
Macros provide an alternative solution: we can record a macro for each exported function: doskey Math::Add=%LOCALAPPDATA%\Commando\Math\Add.cmd $*
. When this macro is recorded the Add function exported by the Math extension can be called from an interactive Windows Command Processor session using following command: Math::Add 1 3 sum
. The extension's name is used as a prefix (Math::
) which acts as a namespace for exported functions, so that multiple extensions can export a function with the same name.
Summary
We now have two extension mechanisms for Windows Command Processor: exporting functions and defining macros. Commando's initialization should make exported functions readily available on the command line and in scripts, and should record all macros defined by all extensions. Part 4 will implement the missing piece of our extension system: initialization.