GetVar.bat gets user input no matter how deviously poison characters are entwined and stores them in a variable name passed to the routine as arg1. Eco.bat spits it back out. Either bat file can be called from a delayed or not expansion environment - that was the hard part and thanks to the work by jeb, dbenham, aGerman and other notables who blazed the trail. Use Eco var and not Eco %var%.
So after all that....
Code: Select all
:GetVar.bat Var="Enter a variable string: " len /m
@echo off
if "%~1" equ "" goto :Help
if "%~1" equ "/?" goto :Help
SetLocal
set "NotDelayedFlag=!"
if Defined NotDelayedFlag EndLocal&goto :GetVar
EndLocal
:Called with Expansion Enabled
setlocal DisableDelayedExpansion
call :GetVar %*
set/a len=%errorlevel%
if /i %len% equ 0 EndLocal&set "%~1="&exit/b 0
SetLocal EnableDelayedExpansion
set "var=!%~1!"
set "Var=!Var:%%=%%~4!"
set "Var=!Var:"=%%~5!"
set "Var=!Var:^=^^^^!"
set "Var=%Var:!=^^^!%" !
set "replace=%% """ ."
for /F "tokens=1,2" %%4 in ("!replace!") do (
EndLocal
EndLocal
set "%~1=%Var%" !
@echo off
exit/b %len%
)
goto :eof
:Help
echo(
echo(SYNTAX: GetVar.bat ^<EnVar^> [="User Prompt: "] [length] [/m]
echo(
echo(Assigns User input to the Environment variable passed as 1st argument
echo(Allows unbalance quotes and 'poison' characters mixed with quotes
echo(The only editing key available to the User is 'backspace'
echo(The user string entered is set in the Environment variable, 'Envar'
echo(If no arguments are passed or '/?' this help message is displayed
echo(The fisrt argument is mandatory, the rest are optional
echo(To display a variable with Poison chars and quotes use: Eco.bat
echo(To mask input with '*'s place /m at the very end of the argument list
echo(
echo(Example:
echo(
echo(GetVar.bat Pa$$word="Enter your 'Poison Password' string: " len /m
echo(Eco.bat "Your Poison Password is: '" Pa$$word "' with length: " len
exit/b 0
::**********************************::
::****|| SUBROUTINE VERSION ||****::
::**********************************::
:GetVar
:: SYNTAX: GetVar ^<EnVar^> [="User Prompt: "] [length] [/m]
::
:: Assigns User input to the Environment variable passed as 1st argument
:: Allows unbalance quotes and 'poison' characters mixed with quotes
:: The only editing key available to the User is 'backspace'
:: The user string entered is set in the Environment variable, 'Envar'
:: If no arguments are passed the routine quits, stand alone version displays help
:: The fisrt argument is mandatory, the rest are optional
:: To display a variable with Poison chars and quotes use: Eco.bat
:: To mask input with '*'s place /m at the very end of the argument list
:: Must be called with delayed expansion disabled for '!', '^' and '&' in string
::
:: Example:
::
:: GetVar.bat Pa$$word="Enter your 'Poison Password' string: " len /m
:: Eco.bat "Your Poison Password is: '" Pa$$word "' with length: " len
:::
::: Dependencies - None Author: Carl with ideas borrowed from Dostips.com
:::
if "%~1"=="" goto :End_GetVar
SetLocal DisableDelayedExpansion
set "Masked="
echo(%*|find /i " /m">nul
if %errorlevel% equ 0 set "Masked=*"
For /F %%# In ('"Prompt;$H&For %%# in (1) Do Rem"') Do Set "BS=%%#"
Set "Line="
if /i "%~2" neq "/m" <Nul set/p=".%BS% %BS%%~2"
:Char_Loop_
Set "Key="
For /F "delims=" %%# In (
'Xcopy /L /W "%~f0" "%~f0" 2^>Nul'
) Do If Not Defined Key Set "Key=%%#"
Set "Key=%Key:~-1%"
SetLocal EnableDelayedExpansion
If Not Defined Key ( Rem Enter pressed
echo(
If not Defined Line EndLocal&EndLocal&(
If Defined %~1 Set "%~1="
If Defined %~3 Set/a "%~3=0
)&exit/b 0
For /F delims^=^ eol^= %%# In ("!Line!") Do (
EndLocal&EndLocal&(
If not "%~3"=="" Set/a "%~3=%length%"
If Not "%~1"=="" (Set "%~1=%%#")
exit/b %length%
)
)
)
If %BS%==^%Key% (
Set "Key="
If Defined Line set/a length-=1& Set "Line=!Line:~0,-1!"& Set /P "=%BS% %BS%" <Nul
) Else (
If defined Masked (Set "Display=*") Else (Set "Display=!Key:~-1!")
set/a length+=1& Set /p=".%BS%!Display!" <Nul
)
If Not Defined Line (
EndLocal& Set/a length=1& Set "Line=%Key%"
) Else For /F delims^=^ eol^= %%# In ("!Line!") Do (
EndLocal& Set/a length=%length%& Set "Line=%%#%Key%"
)
Goto :Char_Loop_
:End_GetVar
EndLocal&exit/b 0
Code: Select all
@echo off&goto :Start_Eco
:Eco.bat "Display quoted strings mixed with " Variables " and more " Vars /n
echo(
echo(SYNTAX: Eco.bat "Envar variable is: '" Envar "'" /n "This is the next line"
echo(
echo(Environment variables may contain poison characters or quotes mixed in.
echo(Quoted strings wil be echo'd as is without the surrounding quotes.
echo('/n' will dsplay a line feed if it is not embedded in quotes.
echo(To assign a variable containing poison characters and quotes use: GetVar.bat
echo(&exit/b
:Start_Eco
if "%~1"=="" goto :Eco.bat
if "%~1"=="/?" goto :Eco.bat
::SetLocal DisableDelayedExpansion
For /F %%# In ('"Prompt;$H&For %%# in (1) Do Rem"') Do Set "BS=%%# %%#"
SetLocal EnableDelayedExpansion
:Start loop
if "%~1"=="" EndLocal&exit/b 0
if /i "/n" equ "%~1" (
echo(
) else if not defined %1 (
set "string=.%BS%%~1"
for /f delims^=^ eol^= %%# in ("!string!") do EndLocal& set/p="%%#" <nul
SetLocal EnableDelayedExpansion
) else ( <nul set/p=".%BS%!%~1!")
shift&goto :Start
:Without Delayed Expansion
for /f tokens^=^1^*^ delims^=^=^ eol^= %%a in ('set %~1') do set/p="%%b" <nul
:end
endlocal&exit/b 0
::**********************************::
::****|| SUBROUTINE VERSION ||****::
::**********************************::
:Eco "Here is a char: " char " and a string: " EnvarString /n "This is line two."
::
:: Echo's strings mixed with environment variables with or without CR/LF or embed CR/LF inside
:: Environment variables must be passed by name (not reference) and may contain poison chars
:: Quoted strings are echo'd as is and may have leading or trailing spaces
:: To place a newline (CF/LF) use '/n' unquoted
:::
::: Dependencies - None
:::
SetLocal DisableDelayedExpansion
For /F %%# In ('"Prompt;$H&For %%# in (1) Do Rem"') Do Set "BS=%%# %%#"
SetLocal EnableDelayedExpansion
:Start_Eco
if "%~1"=="" EndLocal&EndLocal&exit/b
if /i "/n" equ "%~1" (
echo(
) else if not defined %1 (
set "string=.%BS%%~1"
for /f delims^=^ eol^= %%# in ("!string!") do EndLocal& set/p="%%#" <nul
SetLocal EnableDelayedExpansion
) else ( <nul set/p=".%BS%!%~1!")
shift&goto :Start_Eco
:End_Eco