The curious case of the defined, empty, 8192+ long variable
Posted: 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 variablesthen runs a batch file attempting to use themwhich outputsnote 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-scriptthat receives the long variables just fine.
Just another piece in the grand puzzle, I guess
Liviu
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
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
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 . . .
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
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