NT Shell
The Windows NT command shell, CMD.EXE — the 32-bit interactive shell and script interpreter that arrived with Windows NT 3.1 in 1993 and whose NT 4.0 command extensions made 'NT shell scripting' a discipline of its own.
Created by Microsoft (the initial Windows NT command shell is credited to Therese Stowell)
NT Shell is the name the 1990s gave to the Windows NT command shell, CMD.EXE, and to the scripting language it runs. CMD.EXE arrived with Windows NT 3.1 in July 1993. It replaced MS-DOS’s COMMAND.COM as both the interactive prompt and the batch-file interpreter for Microsoft’s new 32-bit operating system. Its language started as a compatible superset of DOS batch. With Windows NT 4.0 in 1996 it gained enough new features (integer arithmetic, subroutines, directory-walking and file-parsing FOR loops) that system administrators began to treat “NT shell scripting” as a discipline of its own. Tim Hill’s 1998 reference, Windows NT Shell Scripting, is named for it.
The program still exists. Every current copy of Windows includes CMD.EXE, and Microsoft still documents it. What is historical is the NT Shell identity: a server-room shell tied to the NT product line, before Windows XP brought the NT kernel to everyone and before PowerShell became Microsoft’s main command shell. This page covers the shell as an environment: interactive mode, the NT 4.0 extensions and the admin practices that grew up around it. The scripting dialect as it survives today has its own page, Windows NT Batch, and its DOS ancestor is covered under DOS Batch.
History & Origins
Windows NT was meant to be a portable, protected-mode, multi-user-capable operating system, and COMMAND.COM did not fit. It was a 16-bit real-mode program. The nearest precedent was the CMD.EXE that Microsoft and IBM had written for OS/2 1.0 (December 1987). Hill’s book traces NT’s two script extensions to these two ancestors: .BAT “was inherited from MS-DOS, while the .CMD type came from OS/2.”
For NT, Microsoft wrote a new CMD.EXE as a native console program. Wikipedia credits the initial NT version to Therese Stowell, citing G. Pascal Zachary’s 1994 account of the NT project, Showstopper!. It shipped with Windows NT 3.1 on July 27, 1993. The design had one hard constraint: existing DOS batch files had to keep working. That constraint has shaped every later change.
The bigger change came with Windows NT 4.0 (1996). Hill’s introduction explains why a book was needed at all: “Aren’t scripts just MS-DOS batch files with a fancy name? … Well, batch files have changed. With the release of Windows NT 4.0, the command shell has been given enough new features to fill a book.” Microsoft called these features command extensions. They were on by default and controlled by two CMD switches of the time, /X (enable) and /Y (disable), plus a per-user EnableExtensions registry value. On current Windows the switches are /E:ON and /E:OFF.
Design Philosophy
The NT Shell has no formal specification. Its principles show up in how it behaves:
- Backward compatibility is non-negotiable. Hill notes that the extensions “are backward compatible, but they can occasionally cause older Windows NT and MS-DOS scripts to fail.” The fix was not to remove features but to provide a switch that, “in effect, runs an MS-DOS compatible command shell.”
- Interactive and script modes are one language. Hill describes the shell as running in either Interactive mode or Script mode. With one or two exceptions, anything that can be typed at the prompt can go in a script, and the reverse.
- Everything is an environment variable. There are no types and no data structures. Values are strings in the process environment, and
SET /Aevaluates integer expressions on top of them. Arrays are simulated with numbered variable names. - The shell is glue. Like a Unix shell, CMD.EXE does little work itself. It sequences external commands such as
NET,XCOPY,ATand the Resource Kit utilities, and passes their exit codes along.
Key Features
The interactive shell
NT’s CMD.EXE was a noticeably better interactive environment than COMMAND.COM:
- Built-in command history and editing. In MS-DOS,
DOSKEYwas a terminate-and-stay-resident (TSR) program that had to be loaded first. In Windows NT, Hill writes, “these features are built into the shell and are always available; DOSKEY merely provides an interface to control them.” F7 pops up a numbered history list, F9 recalls a command by number, andDOSKEYmacros define command aliases. - File-name completion that had to be switched on. NT 4.0 could complete file and directory names, but the
CompletionCharregistry value defaulted to0x0(disabled). Hill suggests setting it to0x9, the Tab key. Microsoft’s current documentation still describes theCompletionChar/PathCompletionCharvalues and the/F:ONswitch, under which Ctrl+D completes directory names and Ctrl+F completes both file and directory names. - AutoRun. Unless CMD is started with
/D, it runs any command stored in theAutoRunvalue underHKLMorHKCU\Software\Microsoft\Command Processorbefore doing anything else. It is the closest thing CMD has to a.profile. - Conditional chaining.
&&runs the next command only if the previous one succeeded,||only if it failed,&sequences commands unconditionally, and parentheses group them.
The NT 4.0 script language
A short script using only features that NT’s extensions added to DOS batch:
| |
- The
%OS%guard. Windows NT always setsOStoWindows_NT. Hill’s skeleton scripts test it on the first lines so that the script exits cleanly on MS-DOS, Windows 3.1, Windows 95 or OS/2. Those lines, and theDOSEXITsection, must therefore use only DOS-compatible syntax. SET /Aevaluates integer expressions with C-style operators, including compound assignment such as+=.CALL :labelandGOTO :EOFgive the language real subroutines with arguments. Before this, batch code reused logic by calling separate.BATfiles.- Extended
FORandIF. NewFORforms walk directory trees and parse file contents or command output, andIFgains numeric comparison operators such asEQU,NEQ,LSSandLEQ. SETLOCAL/ENDLOCALkeep a script’s variable changes local to the script. OS/2’s CMD reportedly already had both commands.
Windows 2000 later added delayed expansion (!VAR!). It fixes the most notorious trap in the language: a %VAR% inside a parenthesised block is expanded once, when the whole block is parsed, not each time the line runs.
Evolution
| Release | What changed in the NT Shell |
|---|---|
| Windows NT 3.1 (1993) | New 32-bit CMD.EXE; DOS batch compatibility; .BAT and .CMD scripts |
| Windows NT 4.0 (1996) | Command extensions: SET /A, CALL :label, GOTO :EOF, extended FOR/IF; /X and /Y switches |
| Windows 2000 (2000) | Delayed expansion with !VAR! |
| Windows XP onward | The NT shell becomes the command prompt on consumer Windows as well |
| PowerShell era (2006 onward) | CMD.EXE kept for compatibility; Microsoft documentation directs advanced users to PowerShell |
After Windows 2000 the language changed little. The most important later events happened around it rather than inside it. In 2001 Windows XP moved home users onto NT, so the “NT Shell” became simply the Windows command prompt. Then Microsoft’s object-pipeline shell project, codenamed Monad, shipped as PowerShell in 2006.
Current Relevance
The NT-era name is gone, and so are most of its practices: NT 4.0 domains, the AT-driven Schedule service and the NT Resource Kit. That is why the encyclopedia lists the shell as historical. The interpreter itself is still in use. CMD.EXE ships with Windows 11 and runs the same .BAT and .CMD files, and Microsoft’s Nano Server container images include it, so the Docker command above works on a Windows container host (not on Linux). Microsoft’s current CMD reference describes nearly the same switches and registry values that Hill documented in 1998, with one addition: a note pointing readers to PowerShell.
Why It Matters
The NT Shell carried DOS batch into the 32-bit era without breaking it. Because NT 4.0’s extensions were on by default but could be switched off, a 1985 batch file and a 1997 logon script could run side by side on the same server. NT 4.0 also gave Windows administrators a built-in automation language present “on every installation”, in Hill’s words, years before Windows Script Host or PowerShell. The way that language was extended (opt-in switches, compatibility kept at every step, quirks never removed) explains both why CMD scripting is so awkward and why scripts written for the NT Shell in the 1990s still run.
Timeline
Notable Uses & Legacy
Windows NT domain logon scripts
NT domain administrators gave each user account a logon script (set with NET USER /SCRIPTPATH). These .BAT/.CMD files ran on the client at logon to map network drives and set up the environment. Tim Hill's 1998 book ships a complete sample logon script.
Scheduled administration jobs
Scripts run unattended by the Windows NT Schedule service (driven from the AT command) handled backups and housekeeping. NT shell scripters learned to map drives explicitly inside the script, because, as Hill puts it, the Schedule service 'operates independently of a user logon', so the drive mappings a logon script creates are not necessarily available.
Windows NT Resource Kit automation
The command-line utilities in the Windows NT Resource Kit were usually combined in shell scripts for user, registry and server administration. Hill's reference covers both and tags each Resource Kit tool so readers know which scripts will run on a plain NT installation.
Build-tool launchers
Many cross-platform tools still start on Windows through a CMD.EXE script. Examples are the Gradle wrapper's gradlew.bat and Apache Maven's mvn.cmd, which find a Java runtime and start the build from the Command Prompt.
Language Influence
Influenced By
Running Today
Run examples using the official Docker image:
docker pull mcr.microsoft.com/windows/nanoserver:ltsc2022Example usage:
docker run --rm mcr.microsoft.com/windows/nanoserver:ltsc2022 cmd /c "echo Hello, World!"