# 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\\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\`, 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 with `FOR /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 /A` supports add (`+`), subtract (`-`), multiply (`*`), integer divide (`/`), modulo (`%%`), bit-shift (`<<`, `>>`), bitwise AND (`&`), OR (`|`), XOR (`^`), NOT (`~`), logical NOT (`!`), grouping `()`, and combined assignment operators (`+=`, `-=`, `*=`, `/=`, `%%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`). Numeric literals: octal prefix `0`, hex prefix `0x`. 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%` and `SET 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 `0123456789ABCDEF` helper 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 `IF` conditions (only for binary math via `SET /A`). AND: nested `IF` statements. 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 use `SET /A "ResultAND = %C1% & %C2%"`, `SET /A "ResultOR = %C1% | %C2%"`, `SET /A "ResultXOR = %C1% ^ %C2%"`. - **Leading Zeroes Gotcha** — `SET /A` treats numbers with leading `0` as octal, so `SET /A x=08` and `SET /A x=09` cause "invalid number" errors. Always strip leading zeroes before arithmetic. Common techniques: use `FOR /F` tokenizing, string manipulation to remove leading zeroes, or `SET /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 =USB` lists all USB devices including disconnected. ## Elevated Privileges - **Check Elevation** — Multiple techniques: (1) `OPENFILES >NUL 2>&1` — fails if not elevated, but `OPENFILES` is 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: if `PROCESSOR_ARCHITEW6432` is 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")` then `UAC.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 newname` supports wildcards: `REN *.txt *.bak`. Undocumented: `REN file.txt *s` chops the filename after the last occurrence of the character. Use `FOR` loops for complex renaming: `FOR %%A IN (*.txt) DO REN "%%A" "%%~nA_backup%%~xA"`. Rename folders with `MOVE oldfolder newfolder`. - **File Properties via FOR Modifiers** — `FOR %%A IN (file) DO` with 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 with `FOR /F`: parse the `/V` output. Comparing dotted version strings: compare each segment numerically (string comparison of `1.10` vs `1.9` fails 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 via `HKEY_CLASSES_ROOT`: parameters `%1` (file path), `%L` (long name), `%W` (working directory). `PATHEXT` controls 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. `RUNAS` may 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 or `pdftk file1.pdf file2.pdf cat output merged.pdf`. Print: Acrobat Reader `/P` or `/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`. The `NUL` trick may fail with junctions/symlinks in NT. `FOR /D` can also match directories: `FOR /D %%A IN (folder) DO ECHO found`. - **FOR /D and FOR /R** — `FOR /D %%A IN (pattern) DO command` matches directories. `FOR /R [path] %%A IN (pattern) DO command` walks directory trees recursively. Combine: `FOR /R "C:\" /D %%A IN (*) DO ECHO %%A` lists all subdirectories. - **RD (RMDIR)** — `RD /S /Q directory` removes directory tree silently. `/S` removes all subdirectories and files. `/Q` suppresses confirmation. Returns errorlevel 2 if directory not found, 145 if directory not empty (when `/S` omitted). - **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` `` (with `usebackq`), or `('command')`. Variable modifiers: `%%~fA` (full path), `%%~dpA` (drive+path), etc. - **Tokens and Delims** — `tokens=1,3` extracts columns 1 and 3 into `%%A` and `%%B`. `tokens=2*` gets column 2 in `%%A` and remainder in `%%B`. `tokens=1-5` gets 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>&1` merges stderr into stdout for combined piping/capture. `>CON` bypasses file redirection and always writes to console. Console output from `CLS` and some commands cannot be redirected. Best practice: `command > logfile 2>&1` to capture both streams. Ambiguity: lines ending in `1` or `2` before `>` 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 /F` to read command output, `ECHO` to screen and `>>file` simultaneously. - **Detect File Encoding** — `FOR /F` loop 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 break `FOR /F`). - **ASCII vs. Unicode Conversion** — `TYPE` does 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: bytes `0xFF 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 with `FINDSTR /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: read `HKCU\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice\ProgID` via `REG QUERY`, returns a value like `FirefoxHTML-308046B0AF4A39CB`. Then look up the executable: `REG QUERY "HKCR\\shell\open\command"` to get the browser path. Old techniques using `ASSOC .html` / `FTYPE` no longer work reliably in Windows 10+. - **Auto-Download Prompt** — Check if a third-party tool exists: `TOOL /? >NUL 2>&1` then `IF ERRORLEVEL 1` means missing. If tool returns non-zero on `/?`, use `(TOOL /? 2>&1) | FIND /I "copyright" >NUL` to detect its output. Prompt user: `SET /P Download=Download now? [y/N]`, then `IF /I "%Download%"=="Y" START "title" "https://download-page"`. Always detect before executing to avoid cryptic `not recognized` errors. - **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 `` and ``. - **FTP Scripting** — `FTP -s:scriptfile hostname` for unattended transfers. Script file contains: `USER username`, password (next line), `cd path`, `binary`, `prompt n`, `mget *.*` (or `mput`). Security: create script on-the-fly with `ECHO` redirection, delete after use (`TYPE NUL >script.ftp & DEL script.ftp`). Check for errors: redirect FTP output to log file, use `FIND` to search for error messages. Alternatives: WGET (`wget ftp://host/file` for 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`. `WHERE` clause 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 but `REG.EXE` is 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 /DISCONNECT` to disconnect. `RASPHONE -h entryname` to 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). Use `CHANGE LOGON /DISABLE` to prevent new logons. ## Login Scripts and Administration - **Network Drive Mapping** — `NET USE G: \\Server\Share /PERSISTENT:No` to map. `NET USE G: /DELETE` to disconnect. Group-based conditional mapping: `NET GROUP "groupname" /DOMAIN | FINDSTR /I "%USERNAME%"` then map if found. Always use `/PERSISTENT:No` in login scripts to prevent stale mappings. - **Network Printer Mapping** — `NET USE LPT1 \\Server\Printer` to connect a printer port. For non-port-based printing, use `RUNDLL32 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 /ALL` parsed with `FOR /F`, or `WMIC 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) or `WRITE /PT file.rtf PrinterName` (silent, specific printer). - **Print Registered File Types** — Technique: use `ASSOC .ext` to get the file type, then look up the print command in `HKCR\FileType\shell\print\command`. HTML: `RUNDLL32.EXE MSHTML.DLL,PrintHTML "%1"`. PDF: read association from registry, extract print command via `REGEDIT /E` or `REG QUERY`. For any registered type: query `HKCR\filetype\shell\print\command` and execute with `START /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 (`/P` print dialog, `/N /T file printer` silent print), Foxit Reader (`/p` silent, `/t file printer`), IrfanView (`/print`, `/convert=output`), OpenOffice (`-pt "Printer" file`), Word (requires VBA macro `winword /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; `/V` verbose with window title, `/SVC` show hosted services, `/FI "filter"` filter by criteria like `IMAGENAME`, `PID`, `STATUS`, `USERNAME`, `MEMUSAGE`; output formats `/FO TABLE|LIST|CSV`). `TASKKILL /PID pid` or `/IM imagename` (kill by PID or name; `/F` force, `/T` tree 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 `/V` shows 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`, not `start=auto`). Service names are the short name, not display name—find via `services.msc` or `SC Query`. ## Program Flow - **Conditional Execution** — `IF condition command`. `IF ... ELSE` requires parentheses: `IF condition (cmd1) ELSE (cmd2)`. `IF ... ELSE IF` chains 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: nested `IF`. 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). `usebackq` enables 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** — `%%~aA` expands to a string of attribute flags like `d--------` (directory) or `--a------` (archive). Attribute positions: `d` (directory), `r` (read-only), `a` (archive), `h` (hidden), `s` (system), plus compressed, encrypted, etc. Test with `IF "%%~aA" GEQ "d" ECHO directory` or 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`–`%%9` and `%%~f0` etc. 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 label` jumps to `:label`. `GOTO:EOF` exits the current subroutine (or batch file if not in a `CALL`ed subroutine). Labels are case-insensitive. Only the first 8 characters of a label are significant in some Windows versions. `GOTO` inside a parenthesized code block (like `FOR` or `IF`) breaks out of that block. - **Continuous FOR /L Loops** — `FOR /L %%A IN (1,0,1) DO command` creates an infinite loop (step=0, never reaches end). Also: `FOR /L %%A IN () DO` or very large end values. Useful for polling/waiting scenarios. - **Breaking Endless Loops** — `Ctrl+C` sends 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 n` is TRUE if errorlevel >= n (not equal!). Exact test: `IF %ERRORLEVEL% EQU 0` (or `NEQ`, `GTR`, `LSS`). Never create a variable named `ERRORLEVEL` (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 0` or `VER >NUL`. Force non-zero: `COLOR 00` (sets errorlevel 1) or `VERIFY OTHER 2>NUL` (sets errorlevel 1). For exact errorlevel checking in DOS: reverse-order `IF ERRORLEVEL` chain (check highest first). - **EXIT** — `EXIT` closes the CMD window entirely. `EXIT /B [exitcode]` exits only the current batch file (or subroutine if called via `CALL`) and optionally sets `%ERRORLEVEL%` to exitcode. Always use `EXIT /B` in batch files to avoid closing the user's terminal. In subroutines: `EXIT /B 0` for 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 with `REGEDIT4`, 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= " %%A IN ('REG QUERY "HKCU\Control Panel\International" /v sCountry') DO SET Country=%%B`. Use `tokens=2*` with asterisk to capture multi-word values. Subcommands: `REG QUERY`, `REG ADD`, `REG DELETE`, `REG COPY`, `REG EXPORT`, `REG IMPORT`. Combine with `FOR /F` to 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's `StdRegProv` class methods like `GetStringValue`, `EnumKey`, `EnumValues`. - **Search the Registry** — Windows 7+ `REG Query` supports `/F` (Find) switch: `REG Query HKLM\Software /F "searchpattern" /S`. Use `/K` to search key names only (fast), `/V` for value names (fast), `/D` for data (slow), or omit for all. Use `/E` for exact matches, `/C` for case-sensitive. Example: `REG Query HKLM\Software /V /F AppPath /S /E` finds 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=%%A` or use built-in `%Date%` and `%Time%` variables (W2K+). Inner `FOR` loop 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 /F` with delimiters (`FOR /F "tokens=1-3 delims=/-" %%A IN ("%Today%") DO ...`) or `SET` substring (`SET Year=%Today:~-4%`, `SET Month=%Today:~-10,2%`). Determine date order via registry: read `iDate` (0=MDY, 1=DMY, 2=YMD) and `sDate` (separator) from `HKCU\Control Panel\International` using `REG QUERY`. Parse time with leading zeros: `SET Now=%Time: =0%` then `SET 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): `:JDate` subroutine takes YYYY MM DD, returns Julian date. `:GDate` converts back. Date arithmetic: `SET /A JPast = JDate - 28` gives 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 `70` selects register, port `71` reads value. Registers: `09`=year, `08`=month, `07`=day, `04`=hours, `02`=minutes, `00`=seconds (all BCD). Register `0E` > `7F` means clock not set. 100% locale-independent but requires admin privileges. - **Delays and Wait Techniques** — `PAUSE` waits for any key. `SLEEP n` (Resource Kit) waits n seconds. `TIMEOUT /T n` (native W7+) waits n seconds or keypress; `/NOBREAK` requires Ctrl+C. PING trick: `PING localhost -n 6 >NUL` delays ~5 seconds (n=seconds+1). CHOICE trick: `REM | CHOICE /C:AB /T:A,10 >NUL` (DOS) or `CHOICE /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 with `CMD /C`. Debug scheduled tasks: schedule `CMD.EXE` with `/INTERACTIVE` to 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 /SE` or `JT /SE P` for 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 `/RU` for run-as account, `/XML` for import/export, `/F` to 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 use `SET /P` in elevated scripts. NT4: `FOR /F "tokens=*" %%A IN ('TYPE CON') DO SET INPUT=%%A` (user presses F6+Enter to finish). MS-DOS: `CHOICE /C:YN` for 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 for `FOR /F` capture. Return errorlevel 0=OK, 2=Cancel. - **Hide or Minimize the Console** — Start minimized: `START /MIN "title" "batch.bat"`. Minimize own window: `CONSOLESTATE /Min` or `SETCONSOLE /minimize` or title+CMDOW combo. Hide own window: `CONSOLESTATE /Hide` or `SETCONSOLE /hide`. Completely hidden (no flash): launch via `RUNNHIDE.EXE batch.bat` or `WSCRIPT.EXE RunNHide.vbs batch.bat` or `HSTART /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 nnnn` displays 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"` then `WSCRIPT 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: `[30m`–`[37m` foreground, `[40m`–`[47m` background, `[1;3Xm` bright. Attributes: `[0m` reset, `[1m` bold, `[4m` underline, `[7m` reverse. Cursor: `[r;cH` position, `[nA/B/C/D` move, `[2J` clear screen, `[K` clear to end of line. In PROMPT strings use `$E` instead 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"`; `/u` for 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= 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.