20090604

http://www.robvanderwoude.com/userinput.php

User Input

Sometimes we need some user interaction in our batch files.
We may need to know to which directory a file is to be copied, for example.
Or which drive needs to be formated.

There are many ways to achieve this user interaction.

The most basic form of user interaction, of course, is the PAUSE command, which halts the batch file until the user presses "any key" (apart from Ctrl, Alt, Shift, CapsLock, NumLock or ScrollLock).
Maybe not really sophisticated, but it works and is always available, in all DOS, Windows and OS/2 versions.
MS-DOS

In the MS-DOS 3 days, a simple Yes/No question could be answered by changing to a temporary directory where two temporary batch files were located, Y.BAT and N.BAT.
Guess what happend if a user typed a completely different answer . . .

Since MS-DOS 6 we have CHOICE.COM (CHOICE.EXE in later versions), a much more versatile and reliable way to solve one character answers like Yes/No.

Unfortunately, the CHOICE command was discontinued in Windows NT 4 and later.
You may want to try my Poor Man's Choice instead, or use DEBUG to create REPLY.COM, as published in Microsoft Knowledge Base article Q77457: Accepting Keyboard Input in Batch Files.

There is another way to receive user input: COPY CON

The command:

COPY CON filename

copies the user input on the command line to the file filename.
To stop entering user input, the user has to type Ctrl+Z (or F6), followed by the Enter key.

Many PC users and batch file authors (including myself), find this approach "less intuitive", to say the least. One would expect that pressing the enter key is enough, and once you find out it isn't, the previous line of input cannot be removed anymore.

The following trick uses ANSI to perform some key translation: the Enter key is translated to the F6 key followed by the Enter key. Thus only one line of input can be entered, and pressing the Enter key sends the input to the temporary file USERINP.TMP.

ECHO Enter some input, and press Enter when ready . . .
ECHO ←[13;0;64;13p
COPY CON USRINPUT.TMP
ECHO ←[13;13p
CLS
ECHO You typed:
TYPE USRINPUT.TMP

Note: The ← character is the Esc character, or ASCII character 27 (or 1B Hexadecimal).
It is a representation of the Esc key.
This Esc character is not to be confused with escape characters!

The previous example is only a bare minimum. The following example not only asks for user input, but stores it in an environment variable USRINPUT as well:

@ECHO OFF
REM * Ask for USeR INPUT and store it in variable USRINPUT
REM * Written by Rob van der Woude

SET USRINPUT=

REM * Turn on ANSI key translation (translate Enter
REM * key to F6+Enter sequence) and ask for input:
ECHO ←[13;0;64;13pEnter one word only . . .

REM * Copy entered text to temporary file:
COPY CON %TEMP%.\~USRINP.TMP

REM * Turn off ANSI key translation and clear irrelevant screen output:
ECHO ←[13;13p←[3A←[K←[1B←[K←[1B←[K←[2A

REM * Add empty line to temporary file. The empty line
REM * will be used to stop DATE asking for new date.
ECHO.>> %TEMP%.\~USRINP.TMP
ECHO.>> %TEMP%.\~USRINP.TMP

REM * Create a temporary batch file that will store the
REM * entered text into the environment variable USRINPUT:
TYPE %TEMP%.\~USRINP.TMP | DATE | FIND "):" > %TEMP%.\~USRINP.BAT

REM * Create more temporary batch files. Add
REM * more command line parameters if necessary,
REM * as in: ECHO SET USRINPUT=%%3 %%4 %%5 %%6 %%7 %%8 %%9>CURRENT.BAT
ECHO SET USRINPUT=%%3>CURRENT.BAT

REM * VOER.BAT and TYP.BAT are replacements for CURRENT.BAT for Dutch
REM * DOS versions; add your own language versions if necessary:
ECHO SET USRINPUT=%%6>VOER.BAT
ECHO SET USRINPUT=%%4>TYP.BAT

REM * This temporary batch file now sets the variable USRINPUT:
CALL %TEMP%.\~USRINP.BAT

REM * Display the result:
ECHO You typed: ←[1m%USRINPUT%←[0m
ECHO.
PAUSE

REM * Finally, clean up the mess of temporary files:
FOR %%A IN (%TEMP%.\~USRINP.BAT %TEMP%.\~USRINP.TMP VOER.BAT TYP.BAT CURRENT.BAT) DO DEL %%A

Click to view source Click to download the ZIPped sources

The previous batch file should work in every DOS version, assuming ANSI.SYS (or one of its replacements, like ANSI.COM) is loaded.
With a few minor adjustments (replace .BAT with .CMD everywhere) it can be used in OS/2 as well. Use READLINE instead, however, in OS/2's DOS sessions.

The following batch file checks if ANSI.SYS is loaded. If so, it will tell the user to press the Enter key only. If not, it will tell the user to press F6 first, followed by the Enter key.
However, to check if ANSI.SYS is loaded, this batch file needs MS-DOS 6 or later.

@ECHO OFF
REM * Asks for USeR INPut and store it in variable USRINPUT
REM * Uses ANSI if available, but works without ANSI too
REM * Assumes MS-DOS 6 or later
REM * Written by Rob van der Woude
REM * http://www.robvanderwoude.com

SET USRINPUT=

REM * Check if ANSI sequences can be used (needs at
REM * least MS-DOS 6 to get an errorlevel from FIND):
SET ANSI=1
MEM /C | FIND "ANSI" > NUL
IF ERRORLEVEL 1 SET ANSI=0

REM * Turn on ANSI key translation (translate Enter
REM * key to F6 + Enter sequence) if possible:
IF "%ANSI%"=="1" ECHO ←[13;0;64;13p

REM * Ask for input:
IF "%ANSI%"=="0" ECHO Enter one word only, and press F6 followed by Enter . . .
IF "%ANSI%"=="1" ECHO Enter one word only, and press Enter . . .

REM * Copy entered text to temporary file:
COPY CON %TEMP%.\~USRINP.TMP

REM * Turn off ANSI key translation and clear irrelevant screen output:
IF "%ANSI%"=="0" CLS
IF "%ANSI%"=="1" ECHO ←[13;13p←[3A←[K←[1B←[K←[1B←[K←[2A

REM * Add empty line to temporary file. The empty line
REM * will be used to stop DATE asking for new date.
ECHO.>> %TEMP%.\~USRINP.TMP
ECHO.>> %TEMP%.\~USRINP.TMP

REM * Create a temporary batch file that will store the
REM * entered text into the environment variable USRINPUT:
TYPE %TEMP%.\~USRINP.TMP | DATE | FIND "):" > %TEMP%.\~USRINP.BAT

REM * Create more temporary batch files. Add
REM * more command line parameters if necessary,
REM * as in: ECHO SET USRINPUT=%%3 %%4 %%5 %%6 %%7 %%8 %%9>CURRENT.BAT
ECHO SET USRINPUT=%%3>CURRENT.BAT

REM * VOER.BAT and TYP.BAT are replacements for CURRENT.BAT for Dutch
REM * DOS versions; add your own language versions if necessary:
ECHO SET USRINPUT=%%6>VOER.BAT
ECHO SET USRINPUT=%%4>TYP.BAT

REM * This temporary batch file now sets the variable USRINPUT:
CALL %TEMP%.\~USRINP.BAT

REM * Display the result:
IF "%ANSI%"=="0" ECHO You typed: %USRINPUT%
IF "%ANSI%"=="1" ECHO You typed: ←[1m%USRINPUT%←[0m
ECHO.
PAUSE

REM * Finally, clean up the mess of temporary files:
FOR %%A IN (%TEMP%.\~USRINP.BAT %TEMP%.\~USRINP.TMP VOER.BAT TYP.BAT CURRENT.BAT) DO DEL %%A
SET ANSI=


Click to view source Click to download the ZIPped sources


In NT we don't need temporary files and we can skip a few lines by using TYPE CON and FOR /F:

@ECHO OFF
:: UserInNT.bat
:: How to use the TYPE CON command to receive user input
:: Written by Rob van der Woude
:: http://www.robvanderwoude.com

ECHO.
ECHO Demonstration of receiving user input through the TYPE CON command.
ECHO Type in any string and close by pressing Enter, F6 (or Ctrl+Z), Enter.
ECHO Only the last non-empty line will be remembered, leading spaces are ignored.
ECHO.

:: Only one single command line is needed to receive user input
FOR /F "tokens=*" %%A IN ('TYPE CON') DO SET INPUT=%%A
:: Use quotes if you want to display redirection characters as well
ECHO You typed: "%INPUT%"

It is still just as un-intuitive as the first COPY CON example, though.

Click to view source Click to download the ZIPped sources

Latest news: Replace TYPE CON by MORE in the above NT batch file and you can save yourself pressing Enter once -- you'll need to press F6, Enter only instead of Enter, F6, Enter, though the latter will still work.
[Tip posted by "Frank" on alt.msdos.batch.nt]

Tom Lavedas' New and Improved Data Input Routine! shows a way to use a graphical box to ask for user input in Windows 95

Duke Communications International, Inc.'s tip # 0323: How can I get a batch file to prompt me for parameters? shows a way to get a graphical box asking for user input in Windows NT

Walter Zackery posted two interesting solutions to obtain user input in NT, on the alt.msdos.batch.nt news group.

One solution uses the FORMAT command, which will fail since it tries to format a diskette in drive A: at 160KB.
If you have a 5¼" drive as your A: drive don't use this one.

The second solution uses the LABEL command.
It will actually change drive C:'s volume label and then restore it again to its old value.
The volume label in NT is restricted to 32 characters, and so is the input string when using this LABEL trick for user input.
Besides that the batch file limits the string to 2 words (1 space) only.

I adapted the original postings so that the batch files no longer need to use temporary files. You can view the original postings at my Solutions found at alt.msdos.batch page.

Click to view source Using FORMAT
Click to view source Using LABEL
Click to download the ZIPped sources


Clay Calvert posted another interesting solution to obtain Yes or No input in most DOS versions by using DEL's /P switch (prompt for confirmation).

Another great solution by Eric Phelps uses a temporary HTA file to obscure a password while it is being typed.
Windows 2000/XP

In Windows 2000, user input can be obtained quite easily by using SET /P

SET /P variable=[promptString]

This command will display an optional promptString where the user can type in a string and press Enter. The typed string will then be stored in the specified environment variable variable.
KiXtart

A non-batch solution for Windows 95/98/NT/2000 users is the GETS function in KiXtart:

@ECHO OFF
:: UsrInKix.bat, Version 1.00 for Win32
:: Batch file using Kix to retrieve user input
:: Written by Rob van der Woude
:: http://www.robvanderwoude.com

:: Create a temporary Kix script that will
:: in turn create a temporary batch file:
> %TEMP%.\UserIn.kix ECHO REDIRECTOUTPUT( "NUL" )
>>%TEMP%.\UserIn.kix ECHO GETS $UserIn
>>%TEMP%.\UserIn.kix ECHO IF OPEN( 1, "@SCRIPTDIR\UserIn.bat", 5 ) = 0
>>%TEMP%.\UserIn.kix ECHO WRITELINE( 1, "SET UserIn=" + $UserIn )
>>%TEMP%.\UserIn.kix ECHO ELSE
>>%TEMP%.\UserIn.kix ECHO ? "Error opening temporary file, errorcode = " + @ERROR
>>%TEMP%.\UserIn.kix ECHO ENDIF
:: Prompt for user input:
ECHO Type anything you like and press Enter when finished:
:: retrieve user input using the Kix script, and
:: then store the result in a temporary batch file:
KIX32.EXE %TEMP%.\UserIn.kix
:: Call the temporary batch file to store
:: the result in an environment variable:
CALL %TEMP%.\UserIn.bat
:: Clean up the temporary files:
IF EXIST %TEMP%.\UserIn.* DEL %TEMP%.\UserIn.*
:: Finaly, display the result:
ECHO You typed: %UserIn%


Click to view source Click to download the ZIPped sources

VBScript

More advanced dialog boxes, output and input, including (masked) password prompts, can be created using VBScript and Internet Explorer, but I would not recommend creating them on the fly.
Sample change password dialog created using VBScript and Internet Explorer

See the VBScript Scripting Techniques section for some of these advanced user message windows.
OS/2

OS/2 users may want to take a look at UserInPM, a utility written in VX-Rexx, displaying a small PM window asking for user input.
It creates a temporary batch file to set an environment variable to the typed input.
An example batch file, with the resulting PM window:

SET USRINPUT=
USRINPUT.EXE Type whatever you like:
CALL USRINPUT.CMD
ECHO User input: %USRINPUT%

USRINPUT dialogue window

You will need the VX-Rexx runtime library VROBJ.DLL to run UserInPM.

No comments:

Post a Comment