1

I was writing a unit test for a script file and noticed that after clearing all the environment variables, set produces no output, yet when I iterate over the set output in a for /f loop, I always get COMSPEC, PATHEXT and PROMPT.

@setlocal
@set prompt=:

@for /f "tokens=1,2 delims==" %%a in ('set') do @set "%%a="
set
@for /f "tokens=1,2 delims==" %%a in ('set') do if "%%a" neq "" @echo %%a %%b
set
@exit /b 878470

Produces:

:test

D:\TMP\Joseph>set

D:\TMP\Joseph>if "COMSPEC" NEQ ""
COMSPEC C:\WINDOWS\system32\cmd.exe

D:\TMP\Joseph>if "PATHEXT" NEQ ""
PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC

D:\TMP\Joseph>if "PROMPT" NEQ ""
PROMPT $P$G

D:\TMP\Joseph>set

 :

I discovered this with a variable counter routine used to verify that my clear variables routine was working correctly. Easy enough to work around, but I'd be interested to know if this is a Win10 only thing or is it a historical feature of cmd.exe?

EDIT: Seems we've established that every new instance of cmd.exe adds COMSPEC, PATHEXT AND PROMPT to its environment if they were missing from its parent environment. Is this special behavior officially defined anywhere or just another one of those undocumented behaviors of cmd.exe?

jwdonahue
  • 5,111
  • 2
  • 14
  • 41
  • 6
    This is because when `for /f` processes an internal command it creates a subprocess of cmd.exe with inherited variables.But it presets some of them. – npocmaka Jan 02 '18 at 20:48
  • @npocmaka, that kind of makes sense, but it's undocumented behavior, to the best of my knowledge. Can you point us to any authoritative sites that mention it? – jwdonahue Jan 02 '18 at 22:24
  • 1
    Probably [this](https://stackoverflow.com/a/4095133/388389) in the **for-loop-command-block** part , but I doubt you'll find something in the MS documentation.Moreover I knew that `for /f` command creates a new cmd instance the preseting these thre variables was new for me. – npocmaka Jan 02 '18 at 23:21
  • 3
    check also this - https://www.dostips.com/forum/viewtopic.php?f=3&t=7006 – npocmaka Jan 02 '18 at 23:29
  • you can try these two lines - `for /f %a in ('set "comspec=" ^& break^|break') do @echo %a` and `set "comspec=" & break|break` – npocmaka Jan 02 '18 at 23:48
  • There are user variables which you can delete and system variables (like `comspec`, `pathext`, `date`, `time`, `random`...), which you can (but shouldn't) "change" (by creating a overriding user variable with the same name). As soon, as you delete it (the user defined one), the system variable takes over again. – Stephan Jan 03 '18 at 07:28
  • 1
    @Stephan, except for some VS/PS cruft, they were all "system variables". Why only these three? Why do they not show up when I run `set` outside of the `for /f` loop? In other words, your assumptions are incorrect. DATE, TIME and RANDOM are indeed special, and they cannot be displayed with `set` unless you override them with local values. COMPSEC, PATHEXT and PROMPT are a different species. They can in fact be deleted. – jwdonahue Jan 03 '18 at 18:32

0 Answers0