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.