The curious case of the defined, empty, 8192+ long variable

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

The curious case of the defined, empty, 8192+ long variable

#1 Post by Liviu » 25 Feb 2013 18:42

http://support.microsoft.com/kb/830473/en-us says that the "Command Prompt ignores any environment variables that are inherited from the parent process and are longer than its own limitations of either 2047 or 8191 characters (as appropriate to the operating system)". This appears to be only partly true - the prompt (and batch files) recognize such a variable to exist ("if defined" succeeds), but can't access its contents, not even the first character.

Following was tried under xp.sp3 and win7.sp1.x64 with identical results. The parent vb-script creates the long variables

Code: Select all

' set819x.vbs

Set wshShell = CreateObject("WScript.Shell")
Set wshEnv = wshShell.Environment("PROCESS")

wshEnv("str8189") = String(8189, "9")
wshEnv("str8190") = String(8190, "0")
wshEnv("str8191") = String(8191, "1")
wshEnv("str8192") = String(8192, "2")
wshEnv("str8193") = String(8193, "3")

wshShell.Run("cmd /c get819x.cmd str8189 str8190 str8191 str8192 str8193 str819x")
wshShell.Run("cmd /c cscript //nologo get819x.vbs str8189 str8190 str8191 str8192 str8193 str819x & echo. & pause")

Set wshEnv = Nothing
Set wshShell = Nothing
then runs a batch file attempting to use them

Code: Select all

:: get819x.cmd

@echo off & setlocal enableDelayedExpansion

:loop
if "%~1" equ "" echo. & pause & goto :eof
call :strlen.edx %~1 len
if defined %~1 (
  echo %~1 is defined, bat.length = !len!, first char = '!%~1:~0,1!'
) else (
  echo %~1 *not* defined, length = !len!
)
shift
goto :loop

:strlen.edx  StrVar  RtnVar
set /a "%~2 = 0"
if "!%~1:~0,1!" equ "" exit /b
@rem use 'if "!%~1:~0,1!" equ "~0,1"' if StrVar might contain spaces
if not defined %~1 exit /b
for %%A in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
  set /a "%~2 |= %%A"
  for %%B in (!%~2!) do if "!%~1:~%%B,1!" == "" set /a "%~2 &= ~%%A"
)
set /a "%~2 += 1" & exit /b
which outputs

Code: Select all

str8189 is defined, bat.length = 8189, first char = '9'
str8190 is defined, bat.length = 8190, first char = '0'
str8191 is defined, bat.length = 8191, first char = '1'
str8192 is defined, bat.length = 0, first char = ''
str8193 is defined, bat.length = 0, first char = ''
str819x *not* defined, length = 0

Press any key to continue . . .
note that variables with values 8192 characters and longer count as both "is defined" and "bat.length = 0".

To verify that the "loss of values" happens in the batch (as opposed to, perhaps, the vbs "run" command, or the "cmd" invocation itself), the second "run" launches a child vb-script

Code: Select all

' get819x.vbs

Set wshShell = CreateObject("WScript.Shell")
Set wshEnv = wshShell.Environment("PROCESS")

For Each arg In Wscript.Arguments
  if wshShell.ExpandEnvironmentStrings("%" & arg & "%") = "%" & arg & "%" then
    Wscript.Echo arg & " *not* defined, vbs.length = " & Len(wshEnv(arg))
  else
    Wscript.Echo arg & " is defined, vbs.length = " & Len(wshEnv(arg))
  end if
Next

Set wshEnv = Nothing
Set wshShell = Nothing
that receives the long variables just fine.

Code: Select all

str8189 is defined, vbs.length = 8189
str8190 is defined, vbs.length = 8190
str8191 is defined, vbs.length = 8191
str8192 is defined, vbs.length = 8192
str8193 is defined, vbs.length = 8193
str819x *not* defined, vbs.length = 0

Press any key to continue . . .

Just another piece in the grand puzzle, I guess ;-)

Liviu

Queue
Posts: 31
Joined: 16 Feb 2013 14:31

Re: The curious case of the defined, empty, 8192+ long varia

#2 Post by Queue » 25 Feb 2013 19:16

Also in line with this, as per viewtopic.php?f=3&t=4312 if you use a cmdcmdline substring / string replacement to ''empty'' the cmdcmdline env var, it will still count as ''defined'' even if it is an empty string.

Code: Select all

rem [%cmdcmdline:~0,0%]
echo [%cmdcmdline%]
if defined cmdcmdline echo yes

Queue

Post Reply