In Windows cmd, how do I prompt for user input and use the result in another command? - windows

I have a Windows .bat file which I would like to accept user input and then use the results of that input as part of the call to additional commands.
For example, I'd like to accept a process ID from the user, and then run jstack against that ID, putting the results of the jstack call into a file. However, when I try this, it doesn't work.
Here's my sample bat file contents:
#echo off
set /p id=Enter ID:
echo %id%
jstack > jstack.txt
and here's what shows up in jstack.txt:
Enter ID: Terminate batch job (Y/N)?

Try this:
#echo off
set /p "id=Enter ID: "
You can then use %id% as a parameter to another batch file like jstack %id%.
For example:
set /P id=Enter id:
jstack %id% > jstack.txt

The syntax is as such: set /p variable=[string]
Check out http://commandwindows.com/batch.htm or http://www.robvanderwoude.com/userinput.php for a more deep dive into user input with the different versions of Windows OS batch files.
Once you have set your variable, you can then go about using it in the following fashion.
#echo off
set /p UserInputPath=What Directory would you like?
cd C:\%UserInputPath%
note the %VariableName% syntax

set /p choice= "Please Select one of the above options :"
echo '%choice%'
The space after = is very important.

I am not sure if this is the case for all versions of Windows, however on the XP machine I have, I need to use the following:
set /p Var1="Prompt String"
Without the prompt string in quotes, I get various results depending on the text.

#echo off
set /p input="Write something, it will be used in the command "echo""
echo %input%
pause
if i get what you want, this works fine. you can use %input% in other commands too.
#echo off
echo Write something, it will be used in the command "echo"
set /p input=""
cls
echo %input%
pause

There is no documented /prompt parameter for SETX as there is for SET.
If you need to prompt for an environment variable that will survive reboots, you can use SETX to store it.
A variable created by SETX won't be usable until you restart the command prompt. Neatly, however, you can SETX a variable that has already been SET, even if it has the same name.
This works for me in Windows 8.1 Pro:
set /p UserInfo= "What is your name? "
setx UserInfo "%UserInfo%"
(The quotation marks around the existing variable are necessary.)
This procedure allows you to use the temporary SET-created variable during the current session and will allow you to reuse the SETX-created variable upon reboot of the computer or restart of the CMD prompt.
(Edited to format code paragraphs properly.)

#echo off
:start
set /p var1="Enter first number: "
pause

You can try also with userInput.bat which uses the html input element.
This will assign the input to the value jstackId:
call userInput.bat jstackId
echo %jstackId%
This will just print the input value which eventually you can capture with FOR /F :
call userInput.bat

There are two possibilities.
You forgot to put the %id% in the jstack call.
jstack %id% > jstack.txt
So the whole correct batch file should be:
#echo off
set /p id=Enter ID:
echo %id%
jstack %id% > jstack.txt
And/Or 2. You did put it in the code (and forgot to tell us in the question) but when you ran the batch file you hit the Enter key instead of typing an ID (say 1234).
What's happening is the result of these two mistakes:
jstack is supposed to be called with the id that you supply it.
But in your case (according to the code you supplied in the question) you called it without any variable. You wrote:
jstack > jstack.txt
So when you run jstack with no variable it outputs the following:
Terminate batch file Y/N?
Your second mistake is that you pressed Enter instead of giving a value when the program asked you: Enter ID:. If you would have put in an ID at this point, say 1234, the %id% variable would become that value, in our case 1234. But you did NOT supply a value and instead pressed Enter. When you don't give the variable any value, and if that variable was not set to anything else before, then the variable %id% is set to the prompt of the set command!! So now %id% is set to Enter ID: which was echoed on your screen as requested in the batch file BEFORE you called the jstack.
But I suspect you DID have the jstack %id% > jstack.txt in your batch file code with the %id (and omitted it by mistake from the question), and that you hit enter without typing in an id. The batch program then echoed the id, which is now "Enter ID:", and then ran jstack Enter ID: > jstack.txt
Jstack itself echoed the input, encountered a mistake and asked to terminate.
And all this was written into the jstack.txt file.

I have a little cmd I use when preparing pc to clients: it calls the user for input, and the rename the pc to that.
#ECHO "remember to run this as admin."
#ECHO OFF
SET /P _inputname= Please enter an computername:
#ECHO Du intastede "%_inputname%"
#ECHO "The pc will restart after this"
pause
#ECHO OFF
wmic computersystem where name="%COMPUTERNAME%" call rename name="%_inputname%"
shutdown -r -f

Dollar signs around the variable do not work on my Vista machine, but percent signs do.
Also note that a trailing space on the "set" line will show up between the prompt and user input.

Just added the
set /p NetworkLocation= Enter name for network?
echo %NetworkLocation% >> netlist.txt
sequence to my netsh batch job. It now shows me the location I respond as the point for that sample. I continuously >> the output file so I know now "home", "work", "Starbucks", etc. Looking for clear air, I can eavulate the lowest use channels and whether there are 5 or just all 2.4 MHz WLANs around.

Just to keep a default value of the variable. Press Enter to use default from the recent run of your .bat:
#echo off
set /p Var1=<Var1.txt
set /p Var1="Enter new value ("%Var1%") "
echo %Var1%> Var1.txt
rem YourApp %Var1%
In the first run just ignore the message about lack of file with the initial value of the variable (or do create the Var1.txt manually).

One other way which might be interesting. You can call a powershell script from where you can do pretty much anything, and send the data bach to cmd or do other stuff with something like this.
set var=myvar;
call "c:\input2.cmd" %var%.
Its kind of more flexible (You can send the data the same way with powershell).
So in your cmd, write this considering the ps script is in C::
PowerShell.exe -ExecutionPolicy unrestricted -Command "& {. C:\Input.ps1}"
And in your input.ps1 script, write this:
$var = Read-Host -Prompt "Your input"
Write-Host "Your var:",$var
#Do stuff with your variable

Related

Windows CMD Start and wait for the default application in a batch file

I am trying to start the default application for a file, wait for it to complete, and then continue with my batch file. The problem is that start, when used below simply creates another command prompt window with the example.doc in the title bar. I can use call instead of start, but then call does not wait for the program to finish before going to the next line. It appears that start needs to have an executable name and will not work with the default application system in windows.
Any ideas how I can make this happen without having to hardcode the windows application in the batch file as well?
set filename=example.doc
start /wait %filename%
copy %filename% %filename%.bak
How do I start the default application for a file, wait for completion, then continue?
It appears that start needs to have an executable name and will not work with the default application system in windows.
start, when used below simply creates another command prompt window with the example.doc in the title bar
start /wait %filename%
The above command won't work because %filename% is used as the window title instead of a command to run.
Always include a TITLE this can be a simple string like "My Script" or just a pair of empty quotes ""
According to the Microsoft documentation, the title is optional, but depending on the other options chosen you can have problems if it is omitted.
Source start
Try the following command instead:
start "" /wait %filename%
Alternative solution using the default open command
Any ideas how I can make this happen without having to hardcode the
windows application in the batch file as well?
One way is to use assoc and ftype to get the default open command used for the file then execute that command.
The following batch file does that for you (so no hard coding of windows applications is needed).
Open.cmd:
#echo off
setlocal enabledelayedexpansion
set _file=example.doc
rem get the extension
for %%a in (%_file%) do (
set _ext=%%~xa
)
rem get the filetype associated with the extension
for /f "usebackq tokens=2 delims==" %%b in (`assoc %_ext%`) do (
set _assoc=%%b
)
rem get the open command used for files of type filetype
for /f "usebackq tokens=2 delims==" %%c in (`ftype %_assoc%`) do (
set _command=%%c
rem replace %1 in the open command with the filename
set _command=!_command:%%1=%_file%!
)
rem run the command and wait for it to finish.
start "" /wait %_command%
copy %_file% %_file%.bak 1>nul
endlocal
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
assoc - Display or change the association between a file extension and a fileType
enabledelayedexpansion - Delayed Expansion will cause variables to be expanded at execution time rather than at parse time.
for - Conditionally perform a command several times.
for /f - Loop command against the results of another command.
ftype - Display or change the link between a FileType and an executable program.
start - Start a program, command or batch script (opens in a new window).
variable edit/replace - Edit and replace the characters assigned to a string variable.
Simply use the filename directly as command, unless that filename is a batch file, in which case use call.
In a batch file invocation of a GUI subsystem executable is blocking, unlike for an interactive command.
Use the start command when you don't want blocking execution.
There is a subtle point about “default application”, namely that a file type can have a registered default application for the graphical shell, e.g. its “Open with…”, without having an assoc/ftype association, or different from that association.
I'm not entirely sure of which registry entries are used for this. I've always had to look it up and research it each time. As I recall it's not well-documented.
But hopefully you're OK with just the assoc/ftype scheme.
A further subtle point about “default application”: on the laptop I'm writing this on the ftype association for text files is to open them in Notepad:
[H:\forums\so]
> assoc .txt
.txt=txtfile
[H:\forums\so]
> ftype txtfile
txtfile=%SystemRoot%\system32\NOTEPAD.EXE %1
[H:\forums\so]
> _
And this is what the graphical shell (Windows Explorer) will do.
But cmd.exe looks inside files, and if it finds an executable signature then it tries to run the text file as an executable, even in Windows 10:
[H:\forums\so]
> echo MZ bah! >oops.txt
[H:\forums\so]
> oops.txt
This version of H:\forums\so\oops.txt is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher.
[H:\forums\so]
> _

A way to Pass a Variable to a Networked path Batch file and Execute

Going to lay this out the best I can and see if someone here can help me out a bit.
Here is my Code .bat on the Remote Server.
echo off
title SystemPlatzAll
set /p input=
findstr %input% SysPlatzAll.log >> Result.txt
%SystemRoot%\explorer.exe "Result.txt"
pause
What im trying to achieve is sending the %input% across the network to this batch file then excute and in return have the file save to the computer it is on. To which then the user will get the file opened from a shared folder i have on the drive.
can I use PsExec to send this over or is there another way?
I can get the .bat to execute with the following.
psexec \\HIFRP010.ad.foo.com -u hoem\hoemfooprod -p !foounit123 -e -h -accepteula -i 0 -d F:\Public\Logfiles\Systemplatz\foo\SystemPlatzBackup1.1\Final\NextTest.bat
pause
The above code will execute the Program.
But I want to know how or if it is possible to instead send %input% from one .bat to another.
Thank you in advance.
It is possible. I am not familiar with psexec, but you may be able to encapsulate the last parameter in doublequotes as is common on windows and pass input params directly on the command line. I do this using runas fairly often.
"F:\Public\Logfiles\Systemplatz\foo\SystemPlatzBackup1.1\Final\NextTest.bat paramFoo paramBar"

How do I make a batch file run strings as commands?

I want to make a batch file to circumvent some cmd problems on my computer, but for that I need to be able to take String user input and run it as a command.
Basically what I want to be able to do is type in a command when the batch file asks for input, and have the computer run that command, similar to python's os module (class?)
Simply assign the string to a variable, then "execute" the variable as though it was a program
eg
set myvar=ECHO Hello, World!
%myvar%
Use the set /p command to prompt for input. This command also displays a message. Example:
#echo off
set "command=dir"
set /p "command=type in a command: "
echo.command is: %command%
echo.press any key or ^<CTRL+C^> to abort . . .
>nul pause
%command%
At its simplest, you want to use set /p to prompt for the command, setting an environment variable to the result, then simply expand the environment variable by itself and the OS will attempt to execute it as a command.
SET /P COMMAND=Command:
%COMMAND%
You can use the batch for loop, this works for me in the command prompt, but not the power shell:
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
C:\Users\Administrator>FOR /F "delims=" %i IN ('python -c "print('set wow=yep')"') DO set toexec=%i
C:\Users\Administrator>set toexec=set wow=yep
C:\Users\Administrator>%toexec%
C:\Users\Administrator>echo %wow%
yep

Is there an equivalent source command in Windows CMD as in bash or tcsh?

I know that in the unix world, if you edit your .profile or .cshrc file, you can do a source ~/.profile or source ~/.cshrc to get the effect on your current session. If I changed something in the system variable on Windows, how can I have it effect the current command prompt session without exiting the command prompt session and opening another command prompt session?
In the usual Windows command prompt (i.e. cmd.exe), just using call mybat.bat did what I wanted. I got all the environment variables it had set.
The dos shell will support .bat files containing just assignments to variables that, when executed, will create the variables in the current environment.
c:> type EnvSetTest.bat
set TESTXYZ=XYZ
c:> .\EnvSetTest.bat
c:> set | find "TESTX"
TESTXYZ=XYZ
c:>
IHTH.
Following example will help you to solve your problem.
env.bat This file is for setting variables. Its contents are given blow.
set name="test3"
test.bat Our main batch file.
call env.bat
call print.bat
pause
Now print.bat batch file to print variables. Its contents given below
echo %name%
I am afraid not, but you can start using Powershell, which does support dot sourcing. Since powershell window is really based on cmd so all your dos command will continue to work, and you gain new power, much more power.
The only way I have found this to work is to launch a new cmd window from my own config window. eg:
#echo off
echo Loading...
setlocal enabledelayedexpansion
call 1.cmd
call 2.bat
...
...
if "%LocalAppData%"=="" set LocalAppData=%UserProfile%\Local Settings\Application Data
SET BLAHNAME=FILE:%LocalAppData%\BLAH
call blah blah
cmd
The last cmd will launch a new cmd prompt with the desired settings exported to the command window.
Here's a workaround for some limited use-cases. You can read-in a file of commands and execute them in-line. For example the calling command file looks like:
echo OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:
echo. ----------------
echo. set-up java
echo. ----------------
echo.
rem call %DEV_SCRIPTS%\setup-java
for /F "tokens=*" %%A in ( %DEV_SCRIPTS%\setup-java.bat ) do (
%%A
)
call %DEV_SCRIPTS%\show-java
:
In the setup-java.bat file you can't use % expansion. You need to use !; e.g.:
set JRE_HOME=!JRE_08!
rem
set JRE_TARGET=!JRE_HOME!
So you are litterally source-ing commands from a text file. You will need to test which commands sourced in this way. It took a few trials just to set some environment variables.
I don't think we can do logic or loops because the command processor scans the file at the start. I am OK just having a simple workaround to reuse shared things like environment definitions. Most other things won't need an actual source command (I am hoping). Good luck.
For example to set VC# vars
C:\Windows\System32\cmd.exe /k "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
Use git bash for windows, it works totally fine!

Pausing a batch file when double-clicked but not when run from a console window?

Is there a way for a batch file (in this case, running on Windows XP) to determine whether it was launched from a command line (i.e. inside a console window) or launched via the shell (e.g. by double-clicking)?
I have a script which I'd like to have pause at certain points when run via the shell, but not when run at a command line. I've seen a similar question on SO, but am unable to use the same solution for two reasons: first, whether or not it pauses needs to be dependent on multiple factors, only one of which is whether it was double-clicked. Second, I'll be distributing this script to others on my team and I can't realistically ask all of them to make registry changes which will affect all scripts.
Is this possible?
Found one :-) – After desperately thinking of what cmd might do when run interactively but not when launching a batch file directly ... I finally found one.
The pseudo-variable %cmdcmdline% contains the command line that was used to launch cmd. In case cmd was started normally this contains something akin to the following:
"C:\Windows\System32\cmd.exe"
However, when launching a batch file it looks like this:
cmd /c ""C:\Users\Me\test.cmd" "
Small demo:
#echo off
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set DOUBLECLICKED=1
if defined DOUBLECLICKED pause
This way of checking might not be the most robust, though, but /c should only be present as an argument if a batch file was launched directly.
Tested here on Windows 7 x64. It may or may not work, break, do something weird, eat children (might be a good thing) or bite you in the nose.
A consolidated answer, derived from much of the information found on this page (and some other stack overflow pages with similar questions). This one does not rely on detecting /c, but actually checks for the name of the script in the command line. As a result this solution will not pause if you double-clicked on another batch and then called this one; you had to double-click on this particular batch file.
:pauseIfDoubleClicked
setlocal enabledelayedexpansion
set testl=%cmdcmdline:"=%
set testr=!testl:%~nx0=!
if not "%testl%" == "%testr%" pause
The variable "testl" gets the full line of the cmd processor call, stripping out all of the pesky double quotes.
The variable "testr" takes "testl" and further strips outs the name of the current batch file name if present (which it will be if the batch file was invoked with a double-click).
The if statement sees if "testl" and "testr" are different. If yes, batch was double-clicked, so pause; if no, batch was typed in on command line (or called from another batch file), go on.
Edit: The same can be done in a single line:
echo %cmdcmdline% | findstr /i /c:"%~nx0" && set standalone=1
In plain English, this
pipes the value of %cmdcmdline% to findstr, which then searches for the current script name
%0 contains the current script name, of course only if shift has not been called beforehand
%~nx0 extracts file name and extension from %0
>NUL 2>&1 mutes findstr by redirecting any output to NUL
findstr sets a non-zero errorlevel if it can't find the substring in question
&& only executes if the preceding command returned without error
as a consequence, standalone will not be defined if the script was started from the command line
Later in the script we can do:
if defined standalone pause
One approach might be to create an autoexec.nt file in the root of c:\ that looks something like:
#set nested=%nested%Z
In your batch file, check if %nested% is "Z" - if it is "Z" then you've been double-clicked, so pause. If it's not "Z" - its going to be "ZZ" or "ZZZ" etc as CMD inherits the environment block of the parent process.
-Oisin
A little more information...
I start with a batch-file (test.cmd) that contains:
#echo %cmdcmdline%
If I double-click the "test.cmd" batch-file from within Windows Explorer, the display of echo %cmdcmdline% is:
cmd /c ""D:\Path\test.cmd" "
When executing the "test.cmd" batch-file from within a Command Prompt window, the display of
echo %cmdcmdline% depends on how the command window was started...
If I start "cmd.exe" by clicking the "Start-Orb" and "Command Prompt" or if I click "Start-Orb" and execute "cmd.exe" from the search/run box. Then I execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is:
"C:\Windows\system32\cmd.exe"
Also, for me, if I click "Command Prompt" from the desktop shortcut, then execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is also:
"C:\Windows\system32\cmd.exe"
But, if I "Right-Click" inside a Windows Explorer window and select "Open Command Prompt Here", then execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is:
"C:\Windows\System32\cmd.exe" /k ver
So, just be careful, if you start "cmd.exe" from a shortcut that contains a "/c" in the "Target" field (unlikely), then the test in the previous example will fail to test this case properly.

Resources