* new skill batch-files * batch-files: codespell, re-run start, suggestions, txt assets codespellrc: add FO for tasklist option validate-readme: re-run npm start apply suggestions from code review batch-files: change asset templates to text files * codespellrc: resolve spelling in comment
68 KiB
Batch Files, Scripts, and Functions
Utility Scripts
Run a Script — Use .CMD extension (preferred over .BAT). Edit in Notepad, run from command prompt or double-click. Use CALL between batch files. Detect launch mode with %CmdCmdLine%. Run PowerShell from CMD: powershell.exe -command "& {script}". Run VBScript: cscript //nologo script.vbs.
Banner — Display text in large ASCII art letters using SET commands. Build 7 rows of characters with variable assignment for each letter (a-z, 0-9, space, dash, period). Echo each row to compose the banner output.
Elevate/UAC — Run with elevated permissions. Methods: (1) Shortcut with "Run as Admin" checkbox, (2) VBScript/PowerShell elevation from command line, (3) Test elevation with FSUTIL or CACLS. Run WITHOUT elevation: SET __COMPAT_LAYER=RunAsInvoker. Fix current directory after elevation: pushd "%~dp0".
Date and Time
DateMath — Add/subtract days from any date using Julian Day Number calculation. Handles Y2K correctly. Supports date subtraction (difference in days) and date+days arithmetic. Uses SETLOCAL/ENDLOCAL with variable passback technique.
GetDate — Get current date independent of locale. Methods: (1) PowerShell get-date -format, (2) Robocopy timestamp parsing (most common), (3) date /t parsing, (4) DOFF.exe, (5) VBScript. Robocopy method creates a temp folder and parses the timestamp from ROBOCOPY /njh /njs.
GetTime — Returns current time into a variable. Handles any regional time delimiter by dynamically detecting separator characters. Ensures leading zero on hours for consistent formatting.
GetGMT — Calculate Greenwich Mean Time using WMIC Win32_LocalTime and Win32_UTCTime. Note: WMIC deprecated in Win10 21H1. PowerShell alternative: (Get-Date).ToUniversalTime().
TimeDiff — Calculate difference between two time values. Handles midnight rollover. Returns HH:MM:ss.hs format. Converts times to hundredths-of-second timecodes for arithmetic.
Timer — Measure elapsed time with Start/Stop/Lap modes using a temp stamp file. Calculates hours:minutes:seconds.hundredths. Handles regional time settings.
String and File Processing
DeQuote — Remove quotes from strings. Simplest: %~1 parameter extension. One-line: Set "var=%var:"=%". Function approach: FOR /F with %%~A. Can detect matched vs unmatched quotes.
Empty — Check if directory is empty: FOR /F %%A in ('dir /b /a "%folder%"') do goto NotEmpty. Alternative with dir /A:-D /B for files-only check. Not recursive for subdirectories.
GenChr — Generate any ASCII/Unicode character (0-255) as a .chr file using MAKECAB with the reserveperfoldersize trick. Handle codepage switching with CHCP.
StampMe — Rename file with date/time stamp using Robocopy timestamp parsing. Output format: filename-YYYY-MM-DD@HH-MM-SS.ext. Supports drag-and-drop (pass filename as %1).
StrLen — Calculate string length using binary search with FOR loop testing positions 4096, 2048, 1024...1. O(log n) performance. Returns length via variable or echo.
ToLower — Convert string to upper/lower case. Method 1: CALL SET with letter-by-letter replacement (handles umlauts/international chars). Method 2: simpler FOR loop with case-insensitive SET replacement.
File System
DelOlder — Delete files older than n days. Methods: (1) ForFiles /d -7, (2) Robocopy /move /minage:7, (3) DateMath.cmd with Julian Day comparison, (4) PowerShell .AddDays(-7).
IsDirectory — Check if path is file or directory using %~a1 attribute expansion. Check first character for d: Set "_attr=%~a1" & If "%_attr:~0,1%"=="d" (echo Directory). Raises ERRORLEVEL 1 if not found.
Whereis — Show full path to any executable. Tests for internal commands first, then searches PATH+PATHEXT. Handles quoted paths with spaces. Returns result via variable or echo.
xlong — List files exceeding MAX_PATH (260 chars). Uses DIR /b /s with substring check at position 256: If not "!name:~256,1!"=="" echo Extra long name: "%%a". PowerShell one-liner alternative: cmd /c dir /s /b | where-object{$_.length -gt 256}.
System and Configuration
ANSI Colours — Available by default in Windows 1909+. Foreground: Esc[30m (black) through Esc[97m (white). Background: Esc[40m through Esc[107m. Formatting: Esc[1m (bold), Esc[4m (underline), Esc[7m (reverse). Reset: Esc[0m. Save ESC to variable: for /f %%a in ('echo prompt $E^| cmd') do set "ESC=%%a". Supports 24-bit RGB in Win10. Enable on older Win10 via registry: [HKCU\Console] VirtualTerminalLevel=dword:1.
Autoexec and AutoRun — Autoexec.bat: legacy MS-DOS; under Windows, only SET statements in C:\autoexec.bat are parsed at boot. AutoRun commands: set HKCU\Software\Microsoft\Command Processor\AutoRun or HKLM equivalent to run commands when CMD opens (useful for DOSKEY macros). Startup locations: %appdata%\Microsoft\Windows\Start Menu\Programs\Startup\, HKCU\...\Run, HKLM\...\Run. Machine startup: use Task Scheduler with "When my computer starts". Disable AutoRun on drives: NoDriveTypeAutoRun registry key; fully disable with iniFileMapping method.
CMD Shell — Pause with Ctrl+S, cancel with Ctrl+C. Tab auto-completion enabled by default. Command history: F7 (list), F8 (search), F9 (by number). Quote processing: CMD strips leading/trailing quotes under specific conditions; use double quotes "" to preserve. Max command line: 8191 chars. Max path: 260 chars. Allow UNC paths: [HKLM\...\Command Processor] DisableUNCCheck=dword:1. .CMD vs .BAT: .CMD resets ERRORLEVEL after every command; .BAT only on error. %COMSPEC% shows which shell is running.
Internal Commands — Commands built into CMD.exe (no external .exe needed): ASSOC, BREAK, CALL, CD, CLS, COLOR, COPY, DATE, DEL, DIR, DPATH, ECHO, ENDLOCAL, ERASE, EXIT, FOR, FTYPE, GOTO, IF, KEYS, MD, MKLINK, MOVE, PATH, PAUSE, POPD, PROMPT, PUSHD, REM, REN, RD, SET, SETLOCAL, SHIFT, START, TIME, TITLE, TYPE, VER, VERIFY, VOL. External commands stored in C:\WINDOWS\System32. Arguments can be passed to internal commands; space before argument can be omitted at command line but include it in scripts.
App Compatibility — Set via registry at HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers (per-user) or HKLM (all users). Syntax: ~ [PrivilegeLevel] [Settings] [CompatibilityMode]. Privilege: RUNASADMIN. Settings: 256COLOR, 16BITCOLOR, 640X480, HIGHDPIAWARE, DPIUNAWARE, GDIDPISCALING DPIUNAWARE, DISABLEDXMAXIMIZEDWINDOWEDMODE. Modes: WIN95, WIN98, WINXPSP2, WINXPSP3, VISTARTM, VISTASP1, VISTASP2, WIN7RTM, WIN8RTM. Example: REG ADD "HKCU\...\AppCompatFlags\Layers" /V "%ProgramFiles%\app\app.exe" /T REG_SZ /D "~ RUNASADMIN WINXPSP2" /F.
Errorlevel and Exit Codes — Most commands return 0 for success. Max range: ±2147483647. Detection methods: (1) IF ERRORLEVEL n (legacy, means >= n), (2) IF %ERRORLEVEL% EQU 0 (preferred). Inside loops, use &&/|| conditional operators or enable DelayedExpansion for !ERRORLEVEL!. Commands that do NOT affect ERRORLEVEL: BREAK, ECHO, ENDLOCAL, FOR, IF, PAUSE, REM, RD, TITLE. Force ERRORLEVEL 1: (CALL). Reset to 0: (call ). Never SET ERRORLEVEL=... (creates user variable that shadows the pseudo-variable). .CMD scripts reset ERRORLEVEL after every internal command; .BAT scripts only on error.
Error Handling — Branch on success/failure with conditional operators: SomeCommand && (echo success) || (echo failed). Gotcha: if last command in success branch errors, the failure branch fires; end success block with (call ). For specific errors: IF %ERRORLEVEL% NEQ 0 (Echo Error &Exit /b 1). DEL returns 0 even on failure; Robocopy returns non-zero on success. For scheduled tasks, exiting with error code logs as failed task.
Display DPI — DPI = √(W² + H²) / ScreenSize. Win10 settings: Settings > Display > Scale and Layout (100-500%). Per-user DPI on terminal servers via registry. Don't set DPI below 96 (fonts break). Citrix: per-user DPI only via registry keys for 96/120/144 DPI.
OOBE — Setup Windows 11 without internet/Microsoft account. Win11 25H2: start ms-cxh:localonly from Shift+F10 CMD prompt during setup. Earlier Win11: OOBE\BYPASSNRO (restarts with "I don't have Internet" option). Manual method: add HKLM\...\OOBE BypassNRO=dword:1 via regedit. Custom user folder name (25H2): Shift+F10 during setup, cd oobe, run SetDefaultUserFolder.cmd, enter name (16 char max).
Recovery Environment — WinRE/Safe Mode/WinPE. Safe mode: hold Shift + Power > Restart, then Troubleshoot > Startup Settings > F4 (safe) or F5 (safe+networking). WinRE: repeatedly power-cycle (hold power 10s, 3 times). WinPE: boot from USB, runs wpeinit automatically. WinPE drive detection script: loop through drive letters A-Z checking for existence of a known file. Create admin account from recovery: rename utilman.exe, copy cmd.exe over it, reboot, click Ease of Access at login to get CMD, NET user demo-user password1 /add then NET localgroup administrators demo-user /add.
64-Bit Detection — Detect 64-bit OS: IF %PROCESSOR_ARCHITECTURE%==x86 (IF NOT DEFINED PROCESSOR_ARCHITEW6432 Set _os=32). Detect 32-bit process on 64-bit: check if PROCESSOR_ARCHITEW6432 is defined. System folders: 32-bit session sees System32 as 32-bit and SysNative as 64-bit; 64-bit session sees System32 as 64-bit and SysWOW64 as 32-bit. Relaunch as 64-bit: %SystemRoot%\Sysnative\cmd.exe /C "%~f0" %*. Run 32-bit: %SystemRoot%\SysWoW64\cmd.exe. Environment: %ProgramFiles% = 64-bit programs, %ProgramFiles(x86)% = 32-bit programs.
Networking and Security
Slow Network Browsing — Desktop.ini parsing slows folder listing; check with NET FILE | Find "desktop.ini" on file server. Fix: delete non-essential desktop.ini files or remove READ_ONLY permission. Corrupted profile permissions: rename C:\Users\<profile>\AppData\Local\Microsoft\Windows from another admin account. Network shortcuts on Desktop/Start menu cause slow refresh when resource unavailable; use explorer /e, \\Server\Share shortcut instead.
LAN Manager Authentication — Controls NTLM authentication levels 0-5 via HKLM\SYSTEM\CurrentControlSet\Control\LSA\LMCompatibilityLevel. NTLMv1 removed in Win11 24H2 and Server 2025. Default level 3 for current OS. Level 0-1: send LM+NTLM. Level 2: send NTLM only. Level 3+: send NTLMv2 only. Levels 4-5 on DC: refuse NTLMv1/LM responses. Increasing above 3 on server can lock out old clients.
Logon Types — Event ID 4624 types: 3=Network (remote file/printer access, credentials not cached), 4=Batch (scheduled tasks, credentials hit disk), 5=Service (service accounts, credentials in LSA secrets), 7=Unlock, 8=Network cleartext (IIS basic auth), 9=New credentials (RunAs /netonly), 10=Remote Interactive (RDP, credentials in lsass), 11=Cached Interactive (offline domain logon, mscache2 format).
File Shares Organization — Split Folder Sharing: two drive mappings per team — S: (Shared, visible to other teams) and T: (Team-only, hidden via Access-Based Enumeration). ABE hides folders user can't access; works well up to a few thousand shares but degrades at tens of thousands. Use two AD groups per team: one for T: drive, one for S: drive access. Home folders map to H: (top of list) or U: (bottom). Default sub-folders help users organize: Admin, Documentation, Meetings, Projects, Resources, Templates.
File Sharing Modes — When creating/opening files, specify FILE_SHARE_READ, FILE_SHARE_WRITE, both, or neither. Both processes must have compatible sharing modes. GENERIC_READ + FILE_SHARE_READ: share with any READ process that also has File_Share_Read. GENERIC_WRITE + FILE_SHARE_WRITE: share with any WRITE process that has File_Share_Write. Incompatible modes = file locked by first process.
NoDrives — Hide drive letters in Explorer via registry DWORD at HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoDrives. Bitmask values: A=1, B=2, C=4, D=8... Z=33554432, ALL=67108863. Hidden drives still accessible by typing letter in address bar. Requires logoff/reboot. Hide disk space color bar: edit HKLM\Software\Classes\Drive\TileInfo and remove System.PercentFull;.
Built-In Groups and Special Identities — Key groups: Administrators (unrestricted access), Domain Admins (admin the domain), Enterprise Admins (forest-wide changes), Account Operators (limited account creation), Backup Operators (backup/restore all files), Server Operators (services, shares, shutdown on DCs). Special identities (implicit): Everyone, Authenticated Users, Interactive, Network, Batch, Service, Creator Owner, Anonymous Logon. Protected Users group provides additional credential protection. KRBTGT is the KDC service account. LocalSystem has full system access. LocalService and NetworkService run with limited privileges.
Active Directory Groups — Security groups: control resource access. Distribution groups: email lists only. Scopes: Global (domain-centric, nest users), Domain Local (assign resource permissions), Universal (simple, all-purpose, replicated to global catalog), Local (SAM-stored, single machine). Best practice: users in Global groups, nest in Domain Local groups for permissions (AGDLP). Single domains: Global groups can nest other Globals; Domain Local for resources prevents wrong-way permission inheritance. Group membership evaluated at logon — changes require re-authentication. Naming: use alphanumerics, dash, underscore; prefix with G- or T- for clarity.
Registry Tweaks (Win11) — Boot: disable lock screen NoLockScreen=1, verbose login verbosestatus=1. Explorer: Win10-style context menus (add InprocServer32 key), default to "This PC" LaunchTo=1, disable Thumbs.db DisableThumbnailCache=1, show hidden files Hidden=1, show file extensions HideFileExt=0. Start Menu: move to left TaskbarAl=0, remove Bing search BingSearchEnabled=0, speed up MenuShowDelay=250. Control Panel: allow appearance/display/screensaver changes, set lock screen wallpaper. Telemetry: disable Copilot/Recall TurnOffWindowsCopilot=1, disable diagnostics AllowTelemetry=0. Updates: auto-download+schedule AUOptions=4, notify only AUOptions=2, disable AUOptions=1.
Miscellaneous
Long Filenames and NTFS — Max path: 260 chars (MAX_PATH = drive + colon + backslash + 256 chars + null). Max filename: 256 chars. Access long paths with \\?\ prefix (disables normalization, allows up to 32,767 chars). Win10 1607+ can opt-in to remove MAX_PATH limit. .BAT vs .CMD: .CMD resets ERRORLEVEL consistently; .BAT does not. .BAT on 32-bit Windows may create .PIF files (security risk). Reserved names: CON, PRN, AUX, NUL, COM0-9, LPT0-9. Illegal chars: / \ : * ? " < > |. 8.3 filenames disabled by default since Win8/Server 2012; disable manually with FSUTIL behavior set disable8dot3 1. Path types: absolute C:\path, UNC \\server\share, device \\.\ or \\?\.
Percent Symbols (% vs %%) — In batch files, %% produces a single %. Parser logic: %%G → FOR parameter value; %1 → command line argument; %var% → variable. At the command line, only single % needed (no batch parameters to conflict). Never name variables with numbers (conflicts with %1 etc). SET /A modulus operator needs %% in batch files. Prefix variables with underscore to avoid numeric name conflicts.
Network Printing — Print$ hidden share delivers drivers to clients. Keep Printer Name and Share Name identical. Use short names (≤8 chars, no spaces) for portability. Printer pools: multiple devices as one virtual printer, routes to first available. Priority: create separate high-priority queue pointing to same device. Default printer is per-user, roams with profiles. LPR protocol for line printers and UNIX interop. Bulk migration with PRINTBRM. Delete stuck printers via registry: HKLM\SYSTEM\CurrentControlSet\Control\Print\Printers\<name>, then restart Print Spooler service. Location-aware printing auto-switches default by network.
Best Practices and Debugging
Batch File Scripting Techniques — Master index of batch scripting categories. Techniques classified as "DOS batch" (COMMAND.COM) or "NT batch" (CMD.EXE). Use COMMAND /C to invoke DOS batch techniques on NT systems. Categories: Best Practices, Debugging, Data/Variables, Devices, Elevation, Files, Folders, Internet, Inventory, Math, Miscellaneous, Network, Printing, Processes/Services, Program Flow, Registry, Samples, Schedulers, Security, Time/Date, UNIX Ports, User Interaction, Wildcards.
COMMAND.COM, SHELL and COMSPEC — COMMAND.COM is DOS 16-bit command interpreter. Syntax: COMMAND [drive:path] [device] [/C command | /K command] [/D] [/E:nnn] [/F] [/MSG] [/P] [/Y] [/Z]. /C closes session after exec, /K keeps session open, /P makes permanent, /E:nnn sets environment size (160–32768 bytes), /F enables fail-by-default (suppresses Abort/Retry/Fail), /Y step-through debug, /Z shows errorlevel of every command. SHELL command in CONFIG.SYS specifies primary interpreter. COMSPEC variable specifies secondary. CMD.EXE is 32-bit replacement for Windows NT 4+. Changes in secondary environment are lost when session closes.
DOs and DON'Ts When Writing Batch Files — DOs: (1) add comments, (2) validate input, (3) doublequote args "%~1", (4) doublequote paths (prevents code insertion exploits from ampersands/spaces), (5) consistent casing, (6) initialize variables, (7) use SETLOCAL/local variables, (8) pass data as subroutine arguments not globals, (9) multi-line indented code blocks in IF/FOR, (10) each command on its own line, (11) avoid one-liners with ampersands, (12) check external command availability/version, (13) specify extensions for externals, (14) specify full paths for externals, (15) debug even when working. DON'Ts: (1) no variables for command names, (2) no nested IF...ELSE, (3) no nested code blocks (use subroutines), (4) no @command hiding except @ECHO OFF, (5) no one-liners, (6) no clever tricks without documentation. Quote: "Debugging is always harder than programming, so if you write code as cleverly as you know how, by definition you will be unable to debug it."
Debugging Batch Files — Techniques: (1) Error messages — REM out @ECHO OFF, redirect all output to log mybatch.bat params > mybatch.log 2>&1, search log for errors. (2) Environment variables — insert SET MyVariable or ECHO %MyVariable% to check values, enable delayed expansion in FOR/code blocks. (3) Complex commands — simplify nested FIND/FINDSTR/FOR /F, test components individually, verify token positions. (4) Subroutines — add counter SET /A Counter += 1 at start, dump all vars with SET. (5) Windows versions — test with CMD.EXE copies from different OS versions (rename as cmdNT4.exe etc.), known issues: REG.EXE v3 vs v2, delayed expansion unavailable on NT4/early Win2K, SET /A integer range differences, NETSH options vary. Version control: VER | FIND "Windows NT".
Comments in Batch Files — Methods: (1) REM — standard, works everywhere, but slows COMMAND.COM on floppy. (2) :: double colons — faster (treated as invalid label, skipped), but MUST be at line start. BREAKS inside code blocks and FOR loops (causes ) was unexpected errors). Exception: single :: immediately followed by non-blank command works in code blocks. (3) Comment blocks — use GOTO EndComment/:EndComment, or EXIT at end of file, or ( without closing ) at file end. (4) %= inline comments =% syntax. Key pitfall: (REM comment & ECHO text) — REM treats everything including ) as comment, opening unmatched paren that eats rest of file. Pipe trick: REM | CHOICE /C:AB /T:A,5 > NUL blocks keyboard input (COMMAND.COM only; CMD.EXE uses TYPE NUL | CHOICE). Best practice: avoid comments inside code blocks; use REM if must; place comments before code blocks.
Input Validation and Security
Prevent Code Insertion Exploits — Batch files are "weakly typed": everything is a string, strings can be commands, no way to distinguish data from code. The %CD% vulnerability: ampersands in folder names cause code execution when %CD% is used unquoted. Solution: doublequote "%CD%" (safe because paths cannot contain doublequotes). For variables that CAN contain doublequotes, quoting does NOT solve the issue. Test batch files for unquoted %CD%: TYPE "%%~A" | FIND /I /N "%%CD" | FINDSTR /R /I /C:"[^""]%%CD[:%%]". Alternatives: use "%CD%", use . or .\ instead of %CD%, abort on ampersands: CD | FIND "&" && EXIT /B 1.
Command Line Input Validation — No fool-proof command line validation exists. Best method: ECHO "%~1"| FIND /I "TEST" (method 7, score 6/7) or ECHO "%~1"| FINDSTR /L /X /I """TEST""" (method 13, score 6.5/7). Weak point: "quotes within" — unterminated doublequotes combined with ampersands enable code insertion. %1 vs %~1: tilde strips surrounding quotes. Demonstration: passing test1"&test2= shows code insertion via unmatched quotes.
Parameter Files — Safer alternative to command line arguments. Plain text file with Parameter=Value per line. Validate with FINDSTR /R /C:"[()&'\"]" "parameterfile"to reject unwanted characters. Parse safe files withFOR /F "tokens=* delims==" %%A IN ('FINDSTR /R /X /C:"[^=][^=]=." "parameterfile"') DO SET Parameter.%%A. Singlequotes safe with usebackq` (but then backquotes are forbidden). For ampersands/doublequotes in input, consider VBScript or PowerShell instead.
Safely Using SET /P — SET /P "Input=prompt: " accepts keyboard input. Code insertion risk: input abc&ping ::1 causes ECHO %Input% to execute ping. Doublequoting "%Input%" fails against embedded doublequotes like abc"&ping ::1&echo "oops. Solution: use delayed variable expansion — SETLOCAL EnableDelayedExpansion then reference as !var!. Delayed expansion resolves at step 3 of command processing (after command splitting at step 2 where injection occurs), so special characters are no longer interpreted. Reject doublequotes: SET Input | FIND """" >NUL then IF NOT ERRORLEVEL 1 SET Input=. Test for all questionable chars: SET Input | FINDSTR /R /C:"[&""|()]". Alternative: use CHOICE for selection instead of free input.
Security Configuration with SeCEdit — Set permissions on files, folders, and registry keys using security templates. Create template via MMC snap-in (Security Templates), configure permissions in GUI, save as .inf file. Edit .inf to keep only changed sections ([Registry Keys], [File Security], [Version], [Profile Description]). Apply via: ECHO y| SECEDIT.EXE /CONFIGURE /CFG myprog.inf /DB dummy.sdb /OVERWRITE /AREAS REGKEYS FILESTORE /LOG myprog.log /QUIET. Doublequotes not allowed in SeCEdit commands — use 8.3 short names for paths with spaces. Test with /VERBOSE switch during development.
SubInACL Permissions Management — Microsoft utility for managing security on files, registry keys, services, shares, printers, and processes. Syntax: SubInAcl [/option...] /object_type object_name [/action[=parameter]...]. Object types: /file, /subdirectories, /keyreg, /subkeyreg, /service, /printer, /share, /process. Key actions: /grant=[Domain\]User[=Access], /revoke, /replace, /display, /setowner, /findsid, /changedomain. Access codes vary by type — File: F=Full, C=Change, R=Read, W=Write, X=Execute; Service: T=Start, O=Stop, P=Pause; Registry: Q=Query, S=Set Value, C=Create SubKey. Example: SUBINACL /verbose=1 /subdirectories "D:\folder" /grant=Users=R.
Variables and Data
The SET Command — Displays, sets, or removes environment variables. Basic: SET variable=value, delete: SET variable=, display prefix matches: SET P shows all vars starting with P. SET /A expression for integer math (Windows NT 4+): supports (), * / %, + -, << >>, & ^ |, assignment operators. Numeric literals: 0x hex, 0b binary, 0 octal — beware 08/09 are invalid octal. Limited to 16- or 32-bit integers depending on Windows version. SET /P variable=prompt (Windows 2000+) prompts for input; pressing Enter alone leaves variable unchanged.
NT SET Features — String substitution: %PATH:str1=str2% replaces occurrences (case-insensitive in XP+). str1 can begin with * to match from start. Substrings: %PATH:~10,5% extracts 5 chars at offset 10. Negative offsets: %PATH:~-10% last 10 chars, %PATH:~0,-2% all but last 2.
Dynamic Environment Variables — Computed on each expansion, don't appear in SET output: %CD% (current directory), %DATE%, %TIME%, %RANDOM% (0–32767), %ERRORLEVEL%, %CMDCMDLINE%, %CMDEXTVERSION%, %HIGHESTNUMANODENUMBER%. Hidden dynamics (discovered via SET ""): %=C:% (current dir on C:), %=ExitCode% (hex last exit), %=ExitCodeAscii%, %__APPDIR__% (exe parent folder with trailing \), %__CD__% (current dir with trailing \). If user sets a dynamic variable name, it overrides the dynamic value; unsetting restores it.
Verify if Variables are Defined — IF DEFINED varname (requires Command Extensions). Safer than IF "%var%"=="" which fails on values with doublequotes or special chars. Hidden/dynamic variables (DATE, CD, RANDOM, etc.) report as defined via IF DEFINED but SET varname returns "not defined" unless explicitly set. Check if dynamic vs static: SET Date >NUL 2>&1 — errorlevel 1 means still dynamic. Demo: FOR %%A IN (COMSPEC __APPDIR__ CD DATE ERRORLEVEL RANDOM TIME) DO (IF DEFINED %%A (...)).
Validate Variables — Check string formats with FINDSTR or FOR /F delims tricks. Hexadecimal: FOR /F "delims=0123456789AaBbCcDdEeFf" %%A IN ("%~1") DO ECHO NOT hex or SET /A "=0x%~1". Decimal: ECHO.%~1| FINDSTR /R /X /C:"[0-9][0-9]*". IPv4: validate 4 dot-separated blocks 0–255 with nested checks (reject 256+, reject non-numeric, reject wrong block count). IPv6: remove interface part (%% and after), check no :::, count colon-separated blocks (8 without ::, fewer with :: allowed), validate each block as 1–4 hex digits. MAC: 6 groups of 2 hex digits separated by : or -. ISBN-13: checksum by alternating multiply by 1 and 3. Luhn algorithm: for credit cards, IMEI — double alternating digits, subtract 9 if >9, compare checksum.
Delayed Variable Expansion — Variables expanded with %var% are resolved when the line is READ, not when executed. Inside FOR loops and code blocks (...), this means %var% gets the value from before the block runs. Enable with SETLOCAL ENABLEDELAYEDEXPANSION or CMD /V:ON. Use !var! instead of %var% for execution-time expansion. Example: SET LIST= then FOR %A IN (*) DO SET LIST=!LIST! %A builds cumulative list. Layout note: FOR %%A IN (...) DO (SET X=%X%%%A) is identical to single-line form — both expand %X% before the loop runs. Bug exists in delayed expansion with certain edge cases.
Escape Characters — Percent % escaped by doubling %% in batch files. Caret ^ escapes special chars in CMD.EXE: ^&, ^<, ^>, ^|, ^^, ^(, ^). Doublequoting also protects special chars but quotes are passed to commands. Exclamation marks (with delayed expansion): use ^^! (double caret needed — single caret consumed in first pass, exclamation in second delayed-expansion pass). FIND escapes doublequotes by doubling: """". FINDSTR regex escapes: \\, \[, \], \", \., \*, \?. CALL adds extra caret escaping to arguments — always test when passing escaped strings to CALL.
Command Line Parameters — %0 is program name, %1–%9 are arguments. %10 is NOT the 10th arg — it's %1 followed by 0. Use SHIFT to rotate parameters (or SHIFT /n to shift from position n). NT features: %* = all args, %~d1 drive, %~p1 path, %~n1 filename, %~x1 extension, %~f1 full path. %CmdCmdLine% = original CMD invocation. Delimiters: commas/semicolons replaced by spaces (unless in quotes), first / after command replaced by space, multiple spaces collapsed. Loop alternative: FOR %%A IN (%*) DO (handle %%A). Validate with GOTO trick: GOTO:%~1 2>NUL / IF ERRORLEVEL 1 (echo invalid).
Random Numbers — %RANDOM% dynamic variable gives 0–32767 range. Techniques: (1) Native: FOR /F "tokens=*" %%A IN ('VER ^| TIME ^| FINDSTR /R "[.,]"') DO FOR %%B IN (%%A) DO SET Random=%%B (hundredths of seconds, not truly random in loops). (2) PowerShell: FOR /F %%A IN ('powershell.exe -Command "Get-Random -Minimum 1 -Maximum 100"') DO SET Random=%%A. (3) Rexx: rexxtry say Random(min, max). (4) VBScript: Randomize then WScript.Echo Int((6 * Rnd) + 1), capture with FOR /F %%A IN ('CSCRIPT //NoLogo random.vbs') DO SET Random=%%A.
String Processing
Get String Length — No native string length function. Brute force: iterate character positions with !var:~%%A,1! until empty. Successive approximation (faster for long strings): binary search using IF NOT "!var:~N!"=="" at powers of 2 (512, 256, 128, ..., 1), accumulating length. Example brute force: SET len=0 / FOR /L %%A IN (0,1,8191) DO IF NOT "!str:~%%A,1!"=="" SET /A len=%%A+1.
FOR /F Tokens and Delims — FOR /F "tokens=n,m* delims=ccc" %%A IN ('command') DO .... Delimiters split input into tokens; multiple consecutive delimiters treated as one. Leading delimiters before first word are ignored (useful for stripping leading spaces: FOR /F "tokens=*" %%A IN (" text") DO ECHO %%A). First specified token maps to %%A, next to %%B, etc. tokens=* captures entire remainder. Escape pipe/redirect chars inside FOR /F parentheses with caret: ^|, ^>. No escaping needed when chars are inside quoted strings like FIND "<03>". Strip leading zeroes: FOR /F "tokens=* delims=0" %%A IN ("00012") DO ECHO %%A.
String Substitution — %var:str1=str2% replaces all occurrences of str1 with str2 in the variable value. Case-insensitive in XP+. str2 can be empty to delete occurrences. str1 can start with * to match everything from start to first occurrence of remainder. Example: SET var=%var:old=new%.
Substrings — %var:~offset,length% extracts substring. Offset 0-based; negative offset counts from end. %var:~-10% last 10 chars. %var:~0,-2% all but last 2. Length omitted = rest of string.
Convert to Upper or Lower Case — Method 1 (SET substitution with delayed expansion): SET %~1=!%~1:a=A! repeated for each letter A–Z. Call as subroutine: CALL :UpCase VarName. Method 2 (FOR loop, no delayed expansion needed): FOR %%i IN ("a=A" "b=B" ...) DO CALL SET "%1=%%%1:%%~i%%". Title case variant replaces " a= A" (space-prefixed). Method 3 (Brad Thone): exploit case-insensitive substitution — SET _Abet=A B C D...Z then FOR %%Z IN (%_Abet%) DO SET _Tmp=!_Tmp:%%Z=%%Z!. Method 4 (FIND trick): FIND returns "file names" in upper case in "File not found" message — FOR /F "tokens=2 delims=-" %%A IN ('FIND "" "%~1" 2^>^&1') DO SET UpCase=%%A (XP+). Method 5 (DIR /L): DIR /L /B ~%%B converts temp filename to lowercase. PowerShell: ('%*').ToUpper() or ('%*').ToLower(). Warning: all SET-based methods vulnerable to code insertion — validate input first.
Align Text to Display as Tables — Pad strings to fixed width: append N spaces then truncate: SET Line=%%A%FortySpaces% / SET Line=!Line:~0,40!. For dynamic column width, measure longest string first with brute-force length check (iterate positions 0..80, set width to max). Full pattern: SET "EightySpaces=..." / first pass FOR /F finds max length / second pass pads and appends second column. Console width detection: FOR /F "tokens=2 delims=:" %%A IN ('MODE CON ^| FIND "Columns"') DO SET ConsoleWidth=%%A.
Arrays in Batch Files — Simulate arrays using variable naming conventions. SET User lists all vars starting with "User". Create array-like sets: SET __Arr.Key1=Value1, SET __Arr.Key2=Value2. Loop through: FOR /F "tokens=2* delims=.=" %%A IN ('SET __Arr.') DO ECHO %%A = %%B. WMIC example: FOR /F "tokens=*" %%A IN ('WMIC LogicalDisk Where "DeviceID='C:'" Get /Format:list ^| FIND "="') DO SET __Disk.%%A. Use FINDSTR /R /C:"=." to skip empty values (WMIC outputs CR/LF pairs in empty fields). Enumerate with SET __Disk. to list all stored properties. Closest approximation to associative arrays/hashtables in batch language.
Math and Arithmetic
- SET /A Arithmetic —
SET /Asupports add (+), subtract (-), multiply (*), integer divide (/), modulo (%%), bit-shift (<<,>>), bitwise AND (&), OR (|), XOR (^), NOT (~), logical NOT (!), grouping(), and combined assignment operators (+=,-=,*=,/=,%%=,&=,|=,^=,<<=,>>=). Numeric literals: octal prefix0, hex prefix0x. 32-bit signed integer limit (−2,147,483,648 to 2,147,483,647); 16-bit on NT4. No exponentiation operator — use a loop multiplying in a variable. No square root — use binary search or PowerShell. - No Floating Point — Batch has no native floating-point. Workaround: multiply by 100 (or 1000), do integer math, then extract whole and fraction parts via string slicing:
SET Whole=%Result:~0,-2%andSET Frac=%Result:~-2%. For truly large or precise math, embed a PowerShell one-liner:powershell -C "expression". - Big Number Workarounds — For numbers exceeding 32-bit range: (1) chop last N digits for approximate math, (2) split into individual digits for arbitrary-precision add/multiply (e.g., process digit-by-digit with carry), (3) call PowerShell or another language.
- Formatting Numbers — Display hex: repeatedly divide by 16, index into
0123456789ABCDEFhelper string using!Convert:~%Digit%,1!. Display octal: divide by 8 loop. Right-align decimals: pad with spaces then chop with!Align:~-8!. File size limit ~107MB when multiplying by 20 (32-bit overflow). PowerShell.ToString("format")is simpler for complex formatting. - Boolean Logic in Conditions — No AND/OR/XOR for
IFconditions (only for binary math viaSET /A). AND: nestedIFstatements. OR: set a temp variable to 0, set to 1 per matching condition, then test. XOR: too complex with nested IF. Better approach: assign each condition to a binary variable (0 or 1), then useSET /A "ResultAND = %C1% & %C2%",SET /A "ResultOR = %C1% | %C2%",SET /A "ResultXOR = %C1% ^ %C2%". - Leading Zeroes Gotcha —
SET /Atreats numbers with leading0as octal, soSET /A x=08andSET /A x=09cause "invalid number" errors. Always strip leading zeroes before arithmetic. Common techniques: useFOR /Ftokenizing, string manipulation to remove leading zeroes, orSET /A "1%var:~-2% - 100"pattern to force decimal interpretation.
Devices and Hardware
- DOS/NT Device Names — Valid logical devices: AUX, CON, PRN, COM1-4, LPT1-3, NUL. In NT, check if a name is a device:
DIR %1 2>NUL | FIND /I "Volume" >NUL— no volume label means it is a device. In DOS, AUX/CON/PRN are shown with current date/time by DIR, so must be checked separately. - DEVCON — Command-line Device Manager alternative from the Windows Driver Kit (WDK). Key commands:
classes(list setup classes),find/findall(find devices, including disconnected),hwids(list hardware IDs),driverfiles(list driver files),install/remove/enable/disable/restart/rescan,reboot,status,resources,update,dp_add/dp_delete/dp_enum(OEM driver packages). Remote:-m:\\machine. Class filter:=ClassName(e.g.,=USB,=Printer,=DiskDrive). Hardware ID:@hwid. Example:DEVCON FindAll =USBlists all USB devices including disconnected.
Elevated Privileges
- Check Elevation — Multiple techniques: (1)
OPENFILES >NUL 2>&1— fails if not elevated, butOPENFILESis 64-bit only and fails in 32-bit processes on 64-bit Windows. (2)CACLS "%SYSTEMROOT%\system32\config\system"— check errorlevel; works if CACLS is available. (3) Most reliable:WHOAMI /Groups | FIND "12288" >NUL— works correctly regardless of 32/64-bit process. Detect 32-bit process on 64-bit Windows: ifPROCESSOR_ARCHITEW6432is set (equals AMD64), it is a 32-bit process in 64-bit OS. - Set Elevation (UAC Prompt) — Create a temporary VBScript on-the-fly:
Set UAC = CreateObject("Shell.Application")thenUAC.ShellExecute "%~snx0", "%*", "%~sdp0", "runas", 1. This restarts the batch file with elevated privileges. Variables are lost on restart (new process), so test elevation first thing. PowerShell check:[Security.Principal.WindowsPrincipal]([Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator).
Files and Folders
- Rename Files —
REN oldname newnamesupports wildcards:REN *.txt *.bak. Undocumented:REN file.txt *schops the filename after the last occurrence of the character. UseFORloops for complex renaming:FOR %%A IN (*.txt) DO REN "%%A" "%%~nA_backup%%~xA". Rename folders withMOVE oldfolder newfolder. - File Properties via FOR Modifiers —
FOR %%A IN (file) DOwith modifiers:%%~nA(name),%%~xA(extension),%%~snA(short 8.3 name),%%~aA(attributes),%%~dA(drive),%%~zA(size bytes),%%~tA(date/time),%%~dpA(drive+path/parent),%%~fA(full qualified path),%%~$PATH:A(first PATH match). Modifiers are combinable:%%~nxA(name+ext),%%~dpnxA(full path),%%~fsA(full short path). - File and Product Versions —
FILEVER /V filename(from Support Tools) displays file/product version, description, company. Extract version withFOR /F: parse the/Voutput. Comparing dotted version strings: compare each segment numerically (string comparison of1.10vs1.9fails because"10" < "9"alphabetically). - START and File Associations —
START "title" [/D path] [/I] [/MIN] [/MAX] [/WAIT] [/B] [/SEPARATE] [/SHARED] [priority] command [args]. Priority classes:/LOW,/NORMAL,/HIGH,/REALTIME,/ABOVENORMAL,/BELOWNORMAL. File associations viaHKEY_CLASSES_ROOT: parameters%1(file path),%L(long name),%W(working directory).PATHEXTcontrols which extensions are resolved without explicit extension. - Temporary Files — Use
"%TEMP%.\tempfile"(with trailing dot) for safe temp paths. Windows 2000%TEMP%often contains spaces — always quote.RUNASmay change%TEMP%to a read-only location. Create unique temp names with%RANDOM%or%TIME::=%. - PDF Commands — Get page count: ExifTool (
-PageCount), GhostScript (gswin32c -q -dNODISPLAY -c "(file) (r) file runpdfbegin pdfpagecount = quit"), PDFtk (pdftk file dump_data | FIND "NumberOfPages"), or native:TYPE file.pdf | FINDSTR /R /C:"/Type\s*/Page"(approximate). Merge: GhostScript orpdftk file1.pdf file2.pdf cat output merged.pdf. Print: Acrobat Reader/Por/T, Foxit/p, GhostScript, or registered print command. - Check Folder Exists — NT:
IF EXIST "folder\"(trailing backslash). DOS:IF EXIST folder\NUL. More robust:PUSHD "folder" && (POPD & ECHO exists) || ECHO not exists. TheNULtrick may fail with junctions/symlinks in NT.FOR /Dcan also match directories:FOR /D %%A IN (folder) DO ECHO found. - FOR /D and FOR /R —
FOR /D %%A IN (pattern) DO commandmatches directories.FOR /R [path] %%A IN (pattern) DO commandwalks directory trees recursively. Combine:FOR /R "C:\" /D %%A IN (*) DO ECHO %%Alists all subdirectories. - RD (RMDIR) —
RD /S /Q directoryremoves directory tree silently./Sremoves all subdirectories and files./Qsuppresses confirmation. Returns errorlevel 2 if directory not found, 145 if directory not empty (when/Somitted). - Wildcards Quirks —
*matches any characters including none;?matches exactly one character. Quirks: wildcards after the 3rd character of the extension are ignored in some commands. Short 8.3 names can cause unexpected matches (a file with a long name may match via its short name).DIR *~*.*returns unpredictable results.DEL *~*.*is dangerous — may delete unexpected files due to short name matching.
Redirection and Encoding
- FOR /F (File/String/Command Parsing) —
FOR /F "options" %%A IN (source) DO command. Options:tokens=(column selection, e.g.,1,3*),delims=(delimiter chars, default space/tab),eol=(comment char, default;),skip=n(skip first N lines),usebackq(changes quoting: back-quotes for commands, double-quotes for filenames, single-quotes for strings). Sources: filename,"string",`command`(withusebackq), or('command'). Variable modifiers:%%~fA(full path),%%~dpA(drive+path), etc. - Tokens and Delims —
tokens=1,3extracts columns 1 and 3 into%%Aand%%B.tokens=2*gets column 2 in%%Aand remainder in%%B.tokens=1-5gets columns 1–5. Default delimiters: space and tab.delims=,;sets comma and semicolon.delims=(nothing) reads the entire line.eol=must be set to empty (or a char not in data) to avoid skipping lines starting with;. - Redirection —
>(overwrite stdout),>>(append stdout),2>(redirect stderr),2>&1(merge stderr into stdout),1>&2(stdout to stderr),|(pipe stdout). File handles: 0=stdin, 1=stdout, 2=stderr. Place redirection before the command for readability:>file ECHO text. Escape with caret:ECHO text ^> not-redirected. Space before>may get echoed as part of the text. - Streams and Redirection Explained — Three standard streams: Standard Output (handle 1), Standard Error (handle 2), Console (CON).
2>&1merges stderr into stdout for combined piping/capture.>CONbypasses file redirection and always writes to console. Console output fromCLSand some commands cannot be redirected. Best practice:command > logfile 2>&1to capture both streams. Ambiguity: lines ending in1or2before>may be misinterpreted as handle numbers. - TEE Equivalent — No native TEE in Windows. Workaround: pipe to a batch/PowerShell script that writes to both screen and file. Or use port of Unix TEE command. Simple batch approximation: use
FOR /Fto read command output,ECHOto screen and>>filesimultaneously. - Detect File Encoding —
FOR /Floop aborts on ASCII 0 (null) characters present in Unicode files. Test:FOR /F %%A IN (file) DO (ECHO ANSI&GOTO:EOF)— if the loop completes without the ECHO executing, the file is Unicode (contains null bytes that breakFOR /F). - ASCII vs. Unicode Conversion —
TYPEdoes not lock files (useful for copying logs in use). Unicode to ASCII:TYPE unicode.txt > ascii.txt. ASCII to Unicode:CMD /U /C TYPE ascii.txt > unicode.txt. Unicode BOM header: bytes0xFF 0xFE. Convert Unix linefeeds to Windows:TYPE input.txt | MORE /E /P > output.txt. - Base64 Encoding/Decoding —
CERTUTIL.EXE -encode inputfile outputfile.b64(encode to Base64).CERTUTIL.EXE -decode inputfile.b64 outputfile(decode from Base64). Output includes header/footer lines (-----BEGIN CERTIFICATE-----/-----END CERTIFICATE-----) that may need stripping withFINDSTR /V "CERTIFICATE". - Hex Encoding/Decoding —
CERTUTIL.EXE -encodehex inputfile outputfile [format]. Formats: default (hex editor view with offsets and ASCII),4(hex only, no ASCII or offsets),12(single continuous hex line). Decode:CERTUTIL.EXE -decodehex hexfile outputfile. PowerShell alternatives:[Convert]::ToHexString()/[Convert]::FromHexString()(.NET 5+). - File Hashes —
CERTUTIL.EXE -hashfile filename [algorithm]. Algorithms: MD2, MD4, MD5, SHA1 (default), SHA256, SHA384, SHA512. Example:CERTUTIL -hashfile myapp.exe SHA256. Alternative: FCIV (File Checksum Integrity Verifier, unsupported Microsoft tool, MD5/SHA1 only). PowerShell:Get-FileHash -Algorithm SHA256 filename.
Internet and Networking
- Get Default Browser — Manual:
START ms-settings:defaultapps. Programmatic: readHKCU\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice\ProgIDviaREG QUERY, returns a value likeFirefoxHTML-308046B0AF4A39CB. Then look up the executable:REG QUERY "HKCR\<ProgID>\shell\open\command"to get the browser path. Old techniques usingASSOC .html/FTYPEno longer work reliably in Windows 10+. - Auto-Download Prompt — Check if a third-party tool exists:
TOOL /? >NUL 2>&1thenIF ERRORLEVEL 1means missing. If tool returns non-zero on/?, use(TOOL /? 2>&1) | FIND /I "copyright" >NULto detect its output. Prompt user:SET /P Download=Download now? [y/N], thenIF /I "%Download%"=="Y" START "title" "https://download-page". Always detect before executing to avoid crypticnot recognizederrors. - E-mail from Batch —
START mailto:user@example.com?subject=Hello%%20World^&body=Message%%20text. Escaping: spaces=%%20, CR/LF=%%0D%%0A, ampersands escaped with caret (^&), double%%for batch. Length limited to max command line (~8191 chars on modern Windows). Only creates the message — user must press Send. For unattended sending: use third-party tools like Blat (SMTP, free) or MailSend (shareware). HTML5 also supports<a href="tel:">and<a href="sms:">. - FTP Scripting —
FTP -s:scriptfile hostnamefor unattended transfers. Script file contains:USER username, password (next line),cd path,binary,prompt n,mget *.*(ormput). Security: create script on-the-fly withECHOredirection, delete after use (TYPE NUL >script.ftp & DEL script.ftp). Check for errors: redirect FTP output to log file, useFINDto search for error messages. Alternatives: WGET (wget ftp://host/filefor anonymous downloads), WinSCP (SFTP/FTP with scripting interface), ScriptFTP (encrypted scripts, self-contained executables). - WMIC (WMI Command Line) — Available XP Pro+ (disabled by default in Windows 11). Commands:
GET(read properties),SET(change),CALL(invoke methods). Output formats:/Format:csv,/Format:list,/Format:htable. Store in variables:FOR /F "tokens=*" %%A IN ('WMIC BIOS Get Manufacturer^,Name /Value ^| FIND "="') DO SET BIOS.%%A.WHEREclause with WQL:WMIC Path Win32_NetworkAdapter Where "PhysicalAdapter=TRUE" Get. Aliases vs full class path:WMIC OS Get=WMIC Path Win32_OperatingSystem Get. Remote:/Node:computer. Non-default namespace:/NameSpace:\\root\other. Registry access possible butREG.EXEis easier. - DMIDecode — Linux/Unix utility ported to Windows for reading DMI/SMBIOS data (hardware info like BIOS, system, baseboard, chassis, processor details) directly from firmware tables without WMI.
- RAS (Remote Access) — Commands for managing dial-up and VPN connections from the command line.
RASDIAL entryname [username password]to connect,RASDIAL /DISCONNECTto disconnect.RASPHONE -h entrynameto hang up. - Terminal Server Commands —
QUERY USER [/SERVER:name](list sessions),QUERY SESSION,LOGOFF sessionid /SERVER:name,TSSHUTDN seconds /SERVER:name /POWERDOWN /DELAY:n /V(shutdown with notification),MSG sessionid message,SHADOW sessionid(remote control). UseCHANGE LOGON /DISABLEto prevent new logons.
Login Scripts and Administration
- Network Drive Mapping —
NET USE G: \\Server\Share /PERSISTENT:Noto map.NET USE G: /DELETEto disconnect. Group-based conditional mapping:NET GROUP "groupname" /DOMAIN | FINDSTR /I "%USERNAME%"then map if found. Always use/PERSISTENT:Noin login scripts to prevent stale mappings. - Network Printer Mapping —
NET USE LPT1 \\Server\Printerto connect a printer port. For non-port-based printing, useRUNDLL32 PRINTUI.DLL,PrintUIEntry /in /n \\Server\Printer. Set default printer:WMIC Path Win32_Printer Where Name='PrinterName' Call SetDefaultPrinter. - Log Computer Access — Create date-based log folders and append login events: log
%COMPUTERNAME%,%USERNAME%, date/time. Capture IP and MAC:IPCONFIG /ALLparsed withFOR /F, orWMIC NIC Where NetEnabled=TRUE Get MACAddress. Check antivirus status via WMI SecurityCenter namespace. - Login Script Best Practices — Keep scripts lean; avoid bloating with unnecessary operations. Skip mapping when connections already exist. Do not map drives on servers. Use dedicated Terminal Server login scripts separate from regular workstation scripts. Test thoroughly across different Windows versions.
- Active Directory Command-Line Tools (DS Tools) —
DSQUERY(find AD objects:DSQUERY USER -name "John*"),DSGET(read properties:DSGET USER "CN=John,DC=corp,DC=com" -email),DSADD(create objects),DSMOD(modify),DSRM(delete),DSMOVE(move/rename). All accept distinguished name (DN) format. Pipe results:DSQUERY USER -inactive 12 | DSMOD USER -disabled yes.
Printing
- Print Text Files — Classic:
PRINT myfile.txt /D:LPT1(requires LPT/COM port). Modern:NOTEPAD /P file.txt(default printer, any text file regardless of association). Wordpad:WRITE /P file.rtf(with print dialog) orWRITE /PT file.rtf PrinterName(silent, specific printer). - Print Registered File Types — Technique: use
ASSOC .extto get the file type, then look up the print command inHKCR\FileType\shell\print\command. HTML:RUNDLL32.EXE MSHTML.DLL,PrintHTML "%1". PDF: read association from registry, extract print command viaREGEDIT /EorREG QUERY. For any registered type: queryHKCR\filetype\shell\print\commandand execute withSTART /MIN. File association parameters:%1(full path),%L(long name),%W(parent folder). - Command-Line Switches for Applications — Extensive collection of print/open/convert switches: Adobe Reader (
/Pprint dialog,/N /T file printersilent print), Foxit Reader (/psilent,/t file printer), IrfanView (/print,/convert=output), OpenOffice (-pt "Printer" file), Word (requires VBA macrowinword /mPrintDefault /q /n), Notepad (/P), Wordpad (/P,/PT), PowerPoint (/PT "Printer" "" "" "File"). Most programs accept the file path as first argument to open it. - Command-Line Printer Control (PRINTUI.DLL) —
RUNDLL32.EXE PRINTUI.DLL,PrintUIEntry [options](Windows 7 shorthand:PRINTUI.EXE [options]). Install printer:/if /b "Name" /f ntprint.inf /r "port:" /m "Model". Delete:/dl /n "Name". Set default:/y /n "Name". Get/set settings:/Xg//Xs. Backup:/Ss /n "printer" /a "file.dat". Restore:/Sr /n "printer" /a "file.dat". Always returns errorlevel 0 — verify success by exporting settings to file and checking existence. Migrate printers: PrintMig 3.1 (W2K/XP/2003) or PRINTBRM (W7/2008+). - DDE Command-Line Control — Programs that act as DDE servers can be controlled from the command line using DDE commands. Tools like CMCDDE and ClassExec send DDE execute/request commands to running applications. Useful for controlling Office apps that lack direct print commands.
- Printer Management Scripts — Windows ships with VBScript printer management scripts in
%windir%\System32\(pattern*prn*.vbs):prnmngr.vbs(add/delete/list printers),prncnfg.vbs(configure),prnport.vbs(manage ports),prndrvr.vbs(manage drivers),prnjobs.vbs(manage print jobs).
Processes and Services
- Managing Processes — Native (XP+):
TASKLIST(list processes;/Vverbose with window title,/SVCshow hosted services,/FI "filter"filter by criteria likeIMAGENAME,PID,STATUS,USERNAME,MEMUSAGE; output formats/FO TABLE|LIST|CSV).TASKKILL /PID pidor/IM imagename(kill by PID or name;/Fforce,/Ttree kill including children). Resource Kit alternatives:KILL pid|pattern,TLIST [-t](tree view),PULIST(process+user). SysInternals:PSKILL [\\remote] pid|name,PSLIST [-d|-m|-x|-t|-s]. Determine own PID:FOR /F "tokens=2" %%A IN ('TASKLIST /V ^| FIND /I "%~0"') DO SET MyPID=%%A(works because TASKLIST/Vshows CMD window title which contains the batch file path). - Shutdown, Reboot, Logoff —
SHUTDOWN /s /t 60 /c "message"(shutdown in 60s with warning),SHUTDOWN /p(immediate),SHUTDOWN /l(logoff),SHUTDOWN /r /t 0(immediate reboot),SHUTDOWN /h(hibernate),SHUTDOWN /a(abort pending shutdown). WMIC:WMIC OS Where Primary=TRUE Call Shutdown|Reboot|Win32Shutdown. Win32Shutdown codes: 0=Logoff, 1=Shutdown, 2=Reboot, +4=Force, 8=Poweroff. Lock workstation:RUNDLL32 USER32.DLL,LockWorkStation. Sleep:RUNDLL32 powrprof.dll,SetSuspendState Sleep. PowerShell:Restart-Computer [-Force],Stop-Computer [-Force],Stop-Computer -ComputerName "remote". SysInternals PSSHUTDOWN for remote machines. - SC (Service Controller) —
SC \\computer [command] [service] [options]. Commands:query(status),start,stop,config(change settings),description,failure(recovery actions),delete,create,qc(query config),qdescription,qfailure. Change startup:SC Config servicename start= auto|disabled|demand. Recovery:SC Failure servicename actions= restart/60000/restart/60000// reset= 120(restart after 1 min on first two failures, no action after). Important: space after=is mandatory (start= auto, notstart=auto). Service names are the short name, not display name—find viaservices.mscorSC Query.
Program Flow
- Conditional Execution —
IF condition command.IF ... ELSErequires parentheses:IF condition (cmd1) ELSE (cmd2).IF ... ELSE IFchains via:IF cond1 (cmd1) ELSE IF cond2 (cmd2) ELSE (cmd3). Command chaining:&(always sequential),&&(execute next only on success/errorlevel 0),||(execute next only on failure/non-zero errorlevel). Combine:(cmd1 && cmd2 && cmd3) || ECHO Error occurred. Logical AND in conditions: nestedIF. Logical OR: set temp variable per condition, test final value. - FOR Loops (DOS and NT) — Basic:
FOR %%A IN (set) DO command.FOR /D %%A IN (pattern) DO(directories only).FOR /R [path] %%A IN (pattern) DO(recursive tree walk).FOR /L %%A IN (start,step,end) DO(numeric range).FOR /F "options" %%A IN (source) DO(parse files/strings/commands). At command prompt use%A; in batch files use%%A. Variables are single-letter, case-sensitive (%%A≠%%a). - FOR /F Details —
tokens=1,3*extracts columns 1 and 3 into%%A/%%B, remainder into%%C.delims=,;sets delimiters.eol=(comment character).skip=n(skip header lines).usebackqenables back-quoted commands and double-quoted filenames. Variable modifiers:%%~fA(full path),%%~dpA(drive+path),%%~nxA(name+ext),%%~zA(file size),%%~tA(timestamp),%%~aA(attributes),%%~$PATH:A(search PATH). Modifiers are combinable. - File Attributes in FOR —
%%~aAexpands to a string of attribute flags liked--------(directory) or--a------(archive). Attribute positions:d(directory),r(read-only),a(archive),h(hidden),s(system), plus compressed, encrypted, etc. Test withIF "%%~aA" GEQ "d" ECHO directoryor parse specific character positions. - Extended FOR Variables — Punctuation characters can serve as FOR variable names:
%%~f#,%%~dp$PATH:!, etc. This allows nested FOR loops without running out of letter variables. Numbers as FOR variables:%%0–%%9and%%~f0etc. work in some contexts but conflict with batch parameters%0–%9. - Mimic While Loops — Do...Until:
:Loop/ do work /IF NOT condition GOTO Loop. Do...While::Loop/IF condition GOTO End/ do work /GOTO Loop/:End. Use unique label names with numeric suffixes (:Loop1,:Loop2) to avoid conflicts. - GOTO —
GOTO labeljumps to:label.GOTO:EOFexits the current subroutine (or batch file if not in aCALLed subroutine). Labels are case-insensitive. Only the first 8 characters of a label are significant in some Windows versions.GOTOinside a parenthesized code block (likeFORorIF) breaks out of that block. - Continuous FOR /L Loops —
FOR /L %%A IN (1,0,1) DO commandcreates an infinite loop (step=0, never reaches end). Also:FOR /L %%A IN () DOor very large end values. Useful for polling/waiting scenarios. - Breaking Endless Loops —
Ctrl+Csends break signal. From another process:TASKKILL /F /IM cmd.exe /FI "WINDOWTITLE eq BatchTitle". Self-breaking: check a flag file or registry value each iteration,IF EXIST stop.flag GOTO End. - Errorlevels —
IF ERRORLEVEL nis TRUE if errorlevel >= n (not equal!). Exact test:IF %ERRORLEVEL% EQU 0(orNEQ,GTR,LSS). Never create a variable namedERRORLEVEL(shadows the dynamic pseudo-variable). Set errorlevel:EXIT /B n(W2K+, exits batch/subroutine and sets errorlevel to n). Reset to 0:CMD /C EXIT 0orVER >NUL. Force non-zero:COLOR 00(sets errorlevel 1) orVERIFY OTHER 2>NUL(sets errorlevel 1). For exact errorlevel checking in DOS: reverse-orderIF ERRORLEVELchain (check highest first). - EXIT —
EXITcloses the CMD window entirely.EXIT /B [exitcode]exits only the current batch file (or subroutine if called viaCALL) and optionally sets%ERRORLEVEL%to exitcode. Always useEXIT /Bin batch files to avoid closing the user's terminal. In subroutines:EXIT /B 0for success,EXIT /B 1(or other non-zero) for failure.
Registry
- REGEDIT — GUI and command-line registry editor. Import (merge):
REGEDIT /S importfile.REG(silent). Export:REGEDIT /E exportfile.REG "HKEY_XXXX\Whatever Key". Remove tree via .REG file: prefix key with minus[-HKEY_CURRENT_USER\DummyTree]. Remove single value:"ValueToBeRemoved"=-. Self-contained .REG batch hybrid: start file withREGEDIT4, use semicolons for batch commands (;@ECHO OFF/;REGEDIT.EXE /S "%~f0"/;EXIT), then registry entries below. Warning: always back up registry before editing. - REG.EXE — Command-line registry tool (Resource Kit for NT4, native since XP). Read values with
FOR /F:FOR /F "tokens=2* delims=<TAB> " %%A IN ('REG QUERY "HKCU\Control Panel\International" /v sCountry') DO SET Country=%%B. Usetokens=2*with asterisk to capture multi-word values. Subcommands:REG QUERY,REG ADD,REG DELETE,REG COPY,REG EXPORT,REG IMPORT. Combine withFOR /Fto extract any registry value into environment variables. - WMIC Registry — Check registry access permissions:
WMIC /NameSpace:\\root\default Class StdRegProv Call CheckAccess. Also query registry values programmatically through WMI'sStdRegProvclass methods likeGetStringValue,EnumKey,EnumValues. - Search the Registry — Windows 7+
REG Querysupports/F(Find) switch:REG Query HKLM\Software /F "searchpattern" /S. Use/Kto search key names only (fast),/Vfor value names (fast),/Dfor data (slow), or omit for all. Use/Efor exact matches,/Cfor case-sensitive. Example:REG Query HKLM\Software /V /F AppPath /S /Efinds all values named exactly "AppPath".
Date and Time
- DATE and TIME Basics in NT — Get current date/time:
FOR /F "tokens=*" %%A IN ('DATE /T') DO SET Today=%%Aor use built-in%Date%and%Time%variables (W2K+). InnerFORloop strips day-of-week prefix. Values are locale-dependent (order of day/month, separators, AM/PM vs 24h all depend on regional settings). - Parsing DATE and TIME — Two approaches:
FOR /Fwith delimiters (FOR /F "tokens=1-3 delims=/-" %%A IN ("%Today%") DO ...) orSETsubstring (SET Year=%Today:~-4%,SET Month=%Today:~-10,2%). Determine date order via registry: readiDate(0=MDY, 1=DMY, 2=YMD) andsDate(separator) fromHKCU\Control Panel\InternationalusingREG QUERY. Parse time with leading zeros:SET Now=%Time: =0%thenSET Hours=%Now:~0,2%. Strip leading zeros:SET /A Hours = 100%Hours% %% 100. - Advanced Date Math — Convert dates to Julian day numbers for arithmetic. Fliegel-Van Flandern algorithm in batch (by Ron Bakowski):
:JDatesubroutine takes YYYY MM DD, returns Julian date.:GDateconverts back. Date arithmetic:SET /A JPast = JDate - 28gives date 4 weeks ago. Weekday from Julian:SET /A WD = %JDate% %% 7(0=Monday...6=Sunday). Age in days: subtract birth Julian from today's Julian. - Read the CMOS Real Time Clock — Use DEBUG to read CMOS RTC registers directly (16-bit only, requires 32-bit OS). Port
70selects register, port71reads value. Registers:09=year,08=month,07=day,04=hours,02=minutes,00=seconds (all BCD). Register0E>7Fmeans clock not set. 100% locale-independent but requires admin privileges. - Delays and Wait Techniques —
PAUSEwaits for any key.SLEEP n(Resource Kit) waits n seconds.TIMEOUT /T n(native W7+) waits n seconds or keypress;/NOBREAKrequires Ctrl+C. PING trick:PING localhost -n 6 >NULdelays ~5 seconds (n=seconds+1). CHOICE trick:REM | CHOICE /C:AB /T:A,10 >NUL(DOS) orCHOICE /C:AB /D:A /T:10 >NUL(W10). PowerShell:powershell -Command "Start-Sleep -Seconds %1". - The AT Command — Schedule commands at absolute times (NT Server):
AT [\\computername] time [/INTERACTIVE] [/EVERY:day,...] command. Uses SYSTEM account by default. Batch files must be preceded withCMD /C. Debug scheduled tasks: scheduleCMD.EXEwith/INTERACTIVEto get a visible prompt in the SYSTEM context. Superseded by SCHTASKS in Windows XP+. - JT (Job Tool) — Windows 2000 Resource Kit tool for Task Scheduler command line management. Enumerate tasks:
JT /SEorJT /SE Pfor full details. Add, edit, or remove scheduled jobs on local/remote computers. Command line switches are unintuitive; use JTHelp.bat to generate HTML help. - SCHTASKS — Full-featured task scheduler CLI (XP+). Subcommands:
/Create(schedule new task),/Delete,/Query,/Change,/Run(run immediately),/End(stop running task),/ShowSid. Create example:SCHTASKS /Create /SC DAILY /TN "MyTask" /TR "C:\script.bat" /ST 21:00. Schedule types: MINUTE, HOURLY, DAILY, WEEKLY, MONTHLY, ONCE, ONSTART, ONLOGON, ONIDLE, ONEVENT. Use/RUfor run-as account,/XMLfor import/export,/Fto force overwrite.
User Interaction
- User Input —
SET /P variable=prompt(W2K+) reads a line of user input. Warning: input containing&,<,>,|or"can cause code injection—never useSET /Pin elevated scripts. NT4:FOR /F "tokens=*" %%A IN ('TYPE CON') DO SET INPUT=%%A(user presses F6+Enter to finish). MS-DOS:CHOICE /C:YNfor single-key Yes/No. PowerShell login dialog:FOR /F "tokens=1* delims=;" %%A IN ('PowerShell ./login.ps1 %UserName%') DO (SET Usr=%%A & SET Pwd=%%B). - Neat Dialog Boxes in Batch Files — C# GUI utilities for batch:
MessageBox.exe(popup message, returns clicked button caption),InputBox.exe(text input with optional password masking, regex filtering, timeout),OpenFileBox.exe/SaveFileBox.exe(file dialogs),OpenFolderBox.exe(folder browser),PrinterSelectBox.exe,DateTimeBox.exe,DropDownBox.exe/RadioButtonBox.exe(list selection),MultipleChoiceBox.exe(checkboxes),ColorSelectBox.exe,FontSelectBox.exe,ProgressBarGUI.exe. All write selection to stdout forFOR /Fcapture. Return errorlevel 0=OK, 2=Cancel. - Hide or Minimize the Console — Start minimized:
START /MIN "title" "batch.bat". Minimize own window:CONSOLESTATE /MinorSETCONSOLE /minimizeor title+CMDOW combo. Hide own window:CONSOLESTATE /HideorSETCONSOLE /hide. Completely hidden (no flash): launch viaRUNNHIDE.EXE batch.batorWSCRIPT.EXE RunNHide.vbs batch.batorHSTART /NOCONSOLE "batch.bat". Note: hiding from within the batch always shows a brief console flash; cloaking must start before the batch. - Error Messages in Local Language —
NET HELPMSG nnnndisplays Windows error message number nnnn in the local system language. Generate a complete list:FOR /L %%A IN (0,1,16384) DO (FOR /F "tokens=*" %%B IN ('NET HELPMSG %%A 2^>NUL') DO ECHO %%A %%B). Use these numbers in batch scripts for localized error output without hardcoding translations. - Popup Messages —
MSG.EXE(XP Pro+): send popup to users/sessions. VBScript on-the-fly:> msg.vbs ECHO WScript.Echo "message"thenWSCRIPT msg.vbs. MSHTA one-liner:MSHTA vbscript:Close(MsgBox("message",vbOKOnly,"title")). PowerShell one-liner:FOR /F "usebackq" %%A IN (\PowerShell -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('message','title','YesNo','Question')"`) DO SET Answer=%%A`. Result is button caption string (Yes, No, OK, Cancel). - ANSI Colors and Escape Sequences — ANSI.SYS required in DOS; built into Windows 10+ CMD.EXE natively. Escape character = ASCII 27. Insert in batch via FORFILES:
FORFILES /P %~dps0 /M %~nxs0 /C "CMD /C ECHO 0x1B[1;31m Red Text 0x1B[0m". Color codes:<Esc>[30m–<Esc>[37mforeground,<Esc>[40m–<Esc>[47mbackground,<Esc>[1;3Xmbright. Attributes:<Esc>[0mreset,<Esc>[1mbold,<Esc>[4munderline,<Esc>[7mreverse. Cursor:<Esc>[r;cHposition,<Esc>[nA/B/C/Dmove,<Esc>[2Jclear screen,<Esc>[Kclear to end of line. In PROMPT strings use$Einstead of the Esc character.
Miscellaneous and Collections
- UNIX Ports (WHICH, TEE, CUT) — Batch/Rexx/Perl/PowerShell/VBScript ports of essential Unix utilities. WHICH: locate executables in PATH (handles DOSKEY macros and CMD internals). TEE: split stdout to both screen and file simultaneously. CUT: extract columns/fields from text. Also includes TRUE/FALSE utilities for explicit errorlevel setting. Available as native batch (.bat), compiled Perl (.exe), and multiple scripting language versions.
- Undocumented NT Commands —
ACINIUPD(W2K Server): update INI files from command line (ACINIUPD /e "file.ini" "section" key "value";/ufor user directory; admin-only).SFC /SCANNOW: scan and replace corrupted protected system files.TSSHUTDN(Terminal Server): controlled server shutdown with user notification, reboot, and powerdown options. - DEBUG — 16-bit DOS debugger repurposed for batch scripting (32-bit OS only; unavailable on 64-bit). Read CMOS Real Time Clock (locale-independent date/time). Read VideoROM manufacturer info. Read I/O port addresses for COM/LPT ports. Check CapsLock/NumLock/ScrollLock status. Create tiny .COM utilities (e.g., REPLY.COM for user input, RESET.COM for reboot). Embed scripts in batch:
DEBUG < %0.BAT/GOTO Around/ script /:Around. - Clever Tips and Tricks — CMD /C quoting quirk:
CMD /C @"command" "arg"(prefix@to prevent misparse when first and last chars are quotes). Elevation check:WHOAMI /GROUPS | FIND "12288"(works in both 32-bit and 64-bit).PUSHD "%~dp0"auto-maps UNC paths to drive letters (works with RUNAS, PSEXEC, UAC).SET /P var=<filereads first line of file into variable. Large number math: FOR loop inserts spaces between digits for per-digit multiplication. FOR /F supports 31 tokens (not just 26) using escaped special characters like%%^^,%%_,%%\``. Swap mouse:RUNDLL32 USER32.DLL,SwapMouseButton. Resolve hostname:FOR /F "tokens=2" %%A IN ('PING -a %1 ^| FIND "[%1]"') DO ECHO %%A. Group commands for single redirect:(cmd1 & cmd2 & cmd3) > log.txt`. - ANSI Art and Console Colors — Use ANSI escape sequences to create colored text screens and animations. ANSI.SYS (DOS) or Windows 10 built-in support. FORFILES technique generates Esc characters on-the-fly. Alternatives:
KOLOR.EXE(set color for text selection in 32/64-bit), BG by Carlos M. (modern BATCHMAN replacement), EKKO by Norman De Forest (ECHO enhancement with PROMPT-like color functions without ANSI driver). - AUTOEXEC.BAT — Automatic startup batch file executed by COMMAND.COM on boot (MS-DOS/Windows 9x). Used to set PATH, load TSRs, configure environment variables, and initialize devices. Not used in Windows NT+ (replaced by registry Run keys and startup folders).
- PHP-Based Batch Files — Technique for mixing PHP code with batch files. PHP CLI processes the script while batch commands are hidden in PHP comments. Useful for leveraging PHP string functions, regex, and web capabilities from within a .bat wrapper.
- Batch HowTos and Sample Collections — Curated collections of batch file techniques, how-to guides, and example scripts covering common Windows administration tasks. Topics include inventory scripts, login scripts, admin tools, network administration, and community-contributed solutions. "Poor Man's Admin Tools" provides lightweight batch-only alternatives to commercial utilities (PMChoice, PMSleep, PMSoon, and others).
- Useful NT Commands for Administrators — Reference of NT commands commonly used in administration batch scripts, including NET commands, SC (service control), TASKLIST/TASKKILL, WMIC, REG, SCHTASKS, ROBOCOPY, ICACLS, and system information utilities.