Access clipboard in Windows batch file - windows

Any idea how to access the Windows clipboard using a batch file?

To set the contents of the clipboard, as Chris Thornton, klaatu, and bunches of others have said, use %windir%\system32\clip.exe.
Update 2:
For a quick one-liner, you could do something like this:
powershell -sta "add-type -as System.Windows.Forms; [windows.forms.clipboard]::GetText()"
Capture and parse with a for /F loop if needed. This will not execute as quickly as the JScript solution below, but it does have the advantage of simplicity.
Updated solution:
Thanks Jonathan for pointing to the capabilities of the mysterious htmlfile COM object for retrieving the clipboard. It is possible to invoke a batch + JScript hybrid to retrieve the contents of the clipboard. In fact, it only takes one line of JScript, and a cscript line to trigger it, and is much faster than the PowerShell / .NET solution offered earlier.
#if (#CodeSection == #Batch) #then
#echo off
setlocal
set "getclip=cscript /nologo /e:JScript "%~f0""
rem // If you want to process the contents of the clipboard line-by-line, use
rem // something like this to preserve blank lines:
for /f "delims=" %%I in ('%getclip% ^| findstr /n "^"') do (
setlocal enabledelayedexpansion
set "line=%%I" & set "line=!line:*:=!"
echo(!line!
endlocal
)
rem // If all you need is to output the clipboard text to the console without
rem // any processing, then remove the "for /f" loop above and uncomment the
rem // following line:
:: %getclip%
goto :EOF
#end // begin JScript hybrid chimera
WSH.Echo(WSH.CreateObject('htmlfile').parentWindow.clipboardData.getData('text'));
Old solution:
It is possible to retrieve clipboard text from the Windows console without any 3rd-party applications by using .NET. If you have powershell installed, you can retrieve the clipboard contents by creating an imaginary textbox and pasting into it. (Source)
Add-Type -AssemblyName System.Windows.Forms
$tb = New-Object System.Windows.Forms.TextBox
$tb.Multiline = $true
$tb.Paste()
$tb.Text
If you don't have powershell, you can still compile a simple .NET application to dump the clipboard text to the console. Here's a C# example. (Inspiration)
using System;
using System.Threading;
using System.Windows.Forms;
class dummy {
[STAThread]
public static void Main() {
if (Clipboard.ContainsText()) Console.Write(Clipboard.GetText());
}
}
Here's a batch script that combines both methods. If powershell exists within %PATH%, use it. Otherwise, find the C# compiler / linker and build a temporary .NET application. As you can see in the batch script comments, you can capture the clipboard contents using a for /f loop or simply dump them to the console.
:: clipboard.bat
:: retrieves contents of clipboard
#echo off
setlocal enabledelayedexpansion
:: Does powershell.exe exist within %PATH%?
for %%I in (powershell.exe) do if "%%~$PATH:I" neq "" (
set getclip=powershell "Add-Type -AssemblyName System.Windows.Forms;$tb=New-Object System.Windows.Forms.TextBox;$tb.Multiline=$true;$tb.Paste();$tb.Text"
) else (
rem :: If not, compose and link C# application to retrieve clipboard text
set getclip=%temp%\getclip.exe
>"%temp%\c.cs" echo using System;using System.Threading;using System.Windows.Forms;class dummy{[STAThread]
>>"%temp%\c.cs" echo public static void Main^(^){if^(Clipboard.ContainsText^(^)^) Console.Write^(Clipboard.GetText^(^)^);}}
for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
if not exist "!getclip!" "%%I" /nologo /out:"!getclip!" "%temp%\c.cs" 2>NUL
)
del "%temp%\c.cs"
if not exist "!getclip!" (
echo Error: Please install .NET 2.0 or newer, or install PowerShell.
goto :EOF
)
)
:: If you want to process the contents of the clipboard line-by-line, use
:: something like this to preserve blank lines:
for /f "delims=" %%I in ('%getclip% ^| findstr /n "^"') do (
set "line=%%I" & set "line=!line:*:=!"
echo(!line!
)
:: If all you need is to output the clipboard text to the console without
:: any processing, then remove the above "for /f" loop and uncomment the
:: following line:
:: %getclip%
:: Clean up the mess
del "%temp%\getclip.exe" 2>NUL
goto :EOF

Slimming it down (on a new enough version of Windows):
set _getclip=powershell "Add-Type -Assembly PresentationCore;[Windows.Clipboard]::GetText()"
for /f "eol=; tokens=*" %I in ('%_getclip%') do set CLIPBOARD_TEXT=%I
First line declares a powershell commandlet.
Second line runs and captures the console output of this commandlet into the CLIPBOARD_TEXT enviroment variable (cmd.exe's closest way to do bash style backtick ` capture)
Update 2017-12-04:
Thanks to #Saintali for pointing out that PowerShell 5.0 adds Get-Clipboard as a top level cmdlets, so this now works as a one liner:
for /f "eol=; tokens=*" %I in ('powershell Get-Clipboard') do set CLIPBOARD_TEXT=%I

The clip command is good to pipe text to the clipboard, but it can't read from the clipboard. There is a way in vbscript / javascript to read / write the clipboard but it uses automation and an invisible instance if Internet Explorer to do it so its pretty fat.
The best tool I've found for working the clipboard from script is Nirsoft's free NirCmd tool.
http://www.nirsoft.net/utils/nircmd.html
Its like a swiss army knife of batch commands all in one small .exe file. For clipboard commands you would say someting like
nircmd clipboard [Action] [Parameter]
Plus you can directly refer to clipboard contents in any of its commands using its ~$clipboard$ variable as an argument. Nircmd also has commands in it to run other programs or commands from so it is possible to use it to pass the clipboard contents as an argument to other batch commands this way.
Clipboard actions:
set - set the specified text into the clipboard.
readfile - set the content of the specified text file into the clipboard.
clear - clear the clipboard.
writefile - write the content of the clipboard to a file. (text only)
addfile - add the content of the clipboard to a file. (text only)
saveimage - Save the current image in the clipboard into a file.
copyimage - Copy the content of the specified image file to the clipboard.
saveclp - Save the current clipboard data into Windows .clp file.
loadclp - Load Windows .clp file into the clipboard.
Note that most programs will always write a plain text copy to the clipboard even when they are writing a special RTF or HTML copy to the clipboard but those are written as content using a different clipboard format type so you may not be able to access those formats unless your program explicitly requests that type of data from the clipboard.

Best way I know, is by using a standalone tool called WINCLIP .
You can get it from here: Outwit
Usage:
Save clipboard to file: winclip -p file.txt
Copy stdout to clipboard: winclip -c Ex: Sed 's/find/replace/' file | winclip -c
Pipe clipboard to sed: winclip -p | Sed 's/find/replace/'
Use winclip output (clipboard) as an argument of another command:
FOR /F "tokens=* usebackq" %%G in ('winclip -p') Do (YOUR_Command %%G ) Note that if you have multiple lines in your clipboard, this command will parse them one by one.
You might also want to take a look at getclip & putclip tools: CygUtils for Windows but winclip is better in my opinion.

With Vista or higher, it's built in. Just pipe output to the "clip" program.
Here's a writeup (by me):
http://www.clipboardextender.com/general-clipboard-use/command-window-output-to-clipboard-in-vista
The article also contains a link to a free utility (written by Me, I think) called Dos2Clip, which can be used on XP.
EDIT: I see that I've gotten the question backwards, my solution OUTPUTS to the clipboard, doesn't read it. sorry!
Update: Along with Dos2Clip, is Clip2Dos (in the same zip), which will send the clipboard text to stdout. So this should work for you. Pascal source is included in the zip.

To retrive clipboard content from your batch script: there is no "pure" batch solution.
If you want an embed 100% batch solution, you will need to generate the other language file from your batch.
Here is a short and batch embed solution which generate a VB file (Usually installed on most windows)

Since all answers are confusing, here my code without delays or extra windows to open stream link copied from clipboard:
#ECHO OFF
//Name of TEMP TXT Files
SET TXTNAME=CLIP.TXT
//VBA SCRIPT
:: VBS SCRIPT
ECHO.Set Shell = CreateObject("WScript.Shell")>_TEMP.VBS
ECHO.Set HTML = CreateObject("htmlfile")>>_TEMP.VBS
ECHO.TXTPATH = "%TXTNAME%">>_TEMP.VBS
ECHO.Set FileSystem = CreateObject("Scripting.FileSystemObject")>>_TEMP.VBS
ECHO.Set File = FileSystem.OpenTextFile(TXTPATH, 2, true)>>_TEMP.VBS
ECHO.File.WriteLine HTML.ParentWindow.ClipboardData.GetData("text")>>_TEMP.VBS
ECHO.File.Close>>_TEMP.VBS
cscript//nologo _TEMP.VBS
:: VBS CLEAN UP
DEL _TEMP.VBS
SET /p streamURL=<%TXTNAME%
DEL %TXTNAME%
:: 1) The location of Player
SET mvpEXE="D:\Tools\Programs\MVP\mpv.com"
:: Open stream to video player
%mvpEXE% %streamURL%
#ECHO ON

Piping output to the clipboard is provided by clip, as others have said. To read input from the clipboard, use the pclip tool in this bundle. And there's tons of other good stuff in there.
So for example, you're going through an online tutorial and you want to create a file with the contents of the clipboard...
c:\>pclip > MyNewFile.txt
or you want to execute a copied command...
c:\>pclip | cmd

This might not be the exact answer, but it will be helpful for your Quest.
Original post:
Visit https://groups.google.com/d/msg/alt.msdos.batch/0n8icUar5AM/60uEZFn9IfAJ
Asked by Roger Hunt
Answered by William Allen
Much Cleaner Steps:
Step 1) create a 'bat' file named Copy.bat in desktop using any text editors and copy and past below code and save it.
#ECHO OFF
SET FN=%1
IF ()==(%1) SET FN=H:\CLIP.TXT
:: Open a blank new file
REM New file>%FN%
ECHO.set sh=WScript.CreateObject("WScript.Shell")>_TEMP.VBS
ECHO.sh.Run("Notepad.exe %FN%")>>_TEMP.VBS
ECHO.WScript.Sleep(200)>>_TEMP.VBS
ECHO.sh.SendKeys("^+{end}^{v}%%{F4}{enter}{enter}")>>_TEMP.VBS
cscript//nologo _TEMP.VBS
ECHO. The clipboard contents are:
TYPE %FN%
:: Clean up
DEL _TEMP.VBS
SET FN=
Step 2) create a Blank text file (in my case 'CLIP.txt' in H Drive) or anywhere, make sure you update the path in Copy.bat file under 'FN=H:\CLIP.txt' with your destination file path.
That's it.
So, basically when you copy any text from anywhere and run Copy.bat file from desktop, it updates CLIP.txt file with the Clipboard contents in it and saves it.
Uses:
I use it to transfer data from remotely connected machines where copy/paste is disabled between different connections; where shared drive (H:) is common to all Connections.

Multiple lines
The problem is resolved, but disappointment remains.
I was forced to split one command into two.
First of them well understands the text and service characters, but does not understand the backspace.
The second understands backspace, but does not understand many service characters.
Can anyone unite them?
Notepad ++, in the place where it should open, is commented out because sometimes the window does not get access to enter characters and therefore you need to make sure that it is active.
Of course, it is better to enter characters using the PID of the notebook process, but ...
The request from wmic opens for a long time, so do not close the notepad window until the bat file is closed.
#echo off
set "like=Microsoft Visual C++"
set "flag=0"
start /max C:\"Program Files\Notepad++\notepad++.exe" -nosession -multiInst
( set LF=^
%= NEWLINE =%
)
set ^"NL=^^^%LF%%LF%^%LF%%LF%^^"
::------------------
setlocal enabledelayedexpansion
for /f "usebackq delims=" %%i in ( `wmic /node:"papa" product where "Name like '%%%like%%%'" get * ^| findstr /r /v "^$"`) do (
for /f tokens^=1^ delims^=^" %%a in ("%%i") do set str=%%a
if "!flag!"=="0" (
::start /max C:\"Program Files\Notepad++\notepad++.exe" -nosession -multiInst& set "flag=1"
for /f "delims=" %%i in ('mshta "javascript:new ActiveXObject('WScript.Shell').SendKeys('{BS}{BS}{BS}{BS}');close(new ActiveXObject('Scripting.FileSystemObject'));"') do set
set flag=1
)
#set /P "_=%%str%%"<NUL|clip
for /f "delims=" %%i in ('mshta "javascript:new ActiveXObject('WScript.Shell').SendKeys('^v');close(new ActiveXObject('Scripting.FileSystemObject'));"') do set
(echo %%NL%%)|clip
for /f "delims=" %%i in ('mshta "javascript:new ActiveXObject('WScript.Shell').SendKeys('^v');close(new ActiveXObject('Scripting.FileSystemObject'));"') do set
)
setlocal disabledelayedexpansion

Here's one way with mshta:
#echo off
:printClip
for /f "usebackq tokens=* delims=" %%i in (
`mshta "javascript:Code(close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(clipboardData.getData('Text'))));"`
) do (
echo cntent of the clipboard:
echo %%i
)
the same thing for accessing it directly from console:
for /f "usebackq tokens=* delims=" %i in (`mshta "javascript:Code(close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(clipboardData.getData('Text'))));"`) do #echo %i

Related

Run Autocad exe and load script file error

This is My first post in here
I need a help for your side I have made a batch file for run autocad exe and load a script file but give error when I run the batch file
#echo off
set KEY_NAME=HKCU\Software\Laxman Enterprises\Xpresslisp Tools
set VALUE_NAME=installpath
set FN=loadload
set FE=scr
FOR /F "tokens=2*" %%A IN ('REG.exe query "%KEY_NAME%" /v "%VALUE_NAME%"') DO (set pInstallDir=%%B)
set approot=%pInstallDir:~0,-1%
echo %approot%\%FN%.%FE%
"C:\Program Files (x86)\AutoCAD 2002\acad.exe" /b %approot%\%FN%.%FE%
pause
Error: while running batch file autocad opens and in commandline the script file not loading "Xpresslisp.scr": Can't find file."
and bellow one is working
script file loading without getting error
#echo off
set path=%USERPROFILE%
set fol=Documents
set NAME=1
set SUFFIX=scr
"C:\Program Files (x86)\AutoCAD 2002\acad.exe" /b %path%\%fol%\%NAME%.%SUFFIX%
pause
Regarding your second question in the comments...
Bellow command will create the text file and write the first line to it e.g. "some text" like in the command below.
Echo some text > full_path_to_txt_file
Command below will append new text to same file.
Echo some text >> full_path_to_txt_file
'>' char creates file and writes firs line
'>>' char append text
check that %path%\%fol%\%NAME%.%SUFFIX% returns the Full Path to the "Xpresslisp.scr" file !
if it does, inspect the Full Path and see if it contains any white spaces.
if it does, enclose the %path%\%fol%\%NAME%.%SUFFIX% with apostrophes
"%path%\%fol%\%NAME%.%SUFFIX%"
It may be something as simple as blindly removing the last character of the installpath without knowing for sure what it is, (doublequote or backslash?).
As there is unlikely to be multiple copies of any filename in the Xpresslisp Tools tree, I would suggest something like this:
#Echo Off
Set "KEY_NAME=HKCU\Software\Laxman Enterprises\Xpresslisp Tools"
Set "VALUE_NAME=installpath"
Set "FN=loadload"
Set "FE=scr"
(Echo=FILEDIA 0
Echo=(LOAD "C:\\loadmyfile.lsp"^)
Echo=FILEDIA 1)>%FN%.%FE%
For /F "Tokens=2*" %%A In ('Reg Query "%KEY_NAME%" /v "%VALUE_NAME%"') Do (
For /F "Delims=" %%C In ('Dir/B/S/A-D "%%~B"\"%FN%.%FE%" 2^>Nul') Do (
Start "" "%ProgramFiles(x86)%\AutoCAD 2002\acad.exe" /b "%%~C"))
This doesn't care if there is a trailing backslash or not and will only run the AutoCAD command if the file is there.

Script hangs when executing in windows batch file

Hello I have a batch file that is used to move text file from on directory to another. The problem is that when there is a text file larger then 7 MB the scrip hangs and freezes the process, which leads to manually force the batch to end.
Why does this bat hang when it moves larger files then 7mb?. How can I solve this to let it move any size text file?
Thank you in advance for your help.
PS. TYPE was used because the original file is in ANSI/UNIX format and the only way we found to convert it to ANSI/PC was using TYPE.
cd /d "c:\users\you\"
for %%i in (*.txt) do (
echo processing %%i
TYPE "%%i" | MORE /P > "c:\temp\%%i"
del "%%i"
)
The purpose of the more command is to present only one page worth of text at a time. When the output device is not a console, the effective page length is very long but not infinite - it will still pause after writing 65534 lines.
Instead, try this:
(for /F "delims=" %%L in (%%i) do #echo %%L) > "c:\temp\%%i"
Command line breakdown:
for /F - read the contents of a file
"delims=" - don't treat spaces or tabs as delimeters
%%L - the variable (same as the %%i in the for command from your original script)
%%i - the file to read
#echo - writes the variable to standard output
( ) > file.txt - redirects standard output to the destination file

Feed in a list of find and replace values with batch

I'm looking for a way to find and replace multiple words in a text file using a Windows batch script.
I know replacing a word can be done so with this bat script:
#echo off &setlocal
set "search=%1"
set "replace=%2"
set "textfile=Input.txt"
set "newfile=Output.txt"
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
del %textfile%
rename %newfile% %textfile%
Now, I just have to take it one step further and feed in the search and replace strings from another file similar to this format:
search_string1, replace_string1
search_string2, replace_string2
search_string3, replace_string3
.
.
.
I would think that I would somehow process the file line by line, and parse them into two variables (search, replace) and then feed that into the script above. Any thoughts? I'm new to Windows batch scripts and have never really made one before so mind my newbie questions.
This type of text replacements are slow and prone to fail when performed via a Batch file. I wrote FindRepl.bat program that is a Batch-JScript hybrid script that not only run much faster and with no errors, but it also allows to perform the multiple replacements you are looking for in just one processing pass of the data file. JScript is a programming language that is included in all Windows versions from XP on. Using FindRepl.bat program you may solve your problem this way:
#echo off
setlocal EnableDelayedExpansion
set "search="
set "replace="
for /F "tokens=1,2 delims=," %%a in (replacements.txt) do (
set "search=!search!|%%a"
set "replace=!replace!|%%b"
)
set "search=!search:~1!"
set "replace=!replace:~1!"
< Input.txt FindRepl =search /A =replace > Output.txt
Note that all text placed after the comma in the replacements file is the replacement string, including spaces.
You may download FindRepl.bat program from this site. Place it in the same folder of previous program or, better yet, in a folder included in %PATH%, so you may use it directly.

Running a non bat extension file as a batch file

Let's say I have a text file, it contains batch commands. How can I run that text file as a batch file from within one, without renaming it. I want too keep a portable aspect too it, so no registry keys or such.
The reason for no renaming is too prevent leftover unrenamed files upon unexpected closure.
The simplest way is this:
cmd < file.txt
As in the previous answers, there are several commands that will not work in this file, like GOTO, SETLOCAL and others. However, multiline nested if and for commands do work as long as for replaceable parameters use just one percent (like in the command-line).
Although this method alaways show in the screen the executed commands (#echo off not works here), you may redirect the output to NUL and in the "Batch" file redirect the desired output to CON. For example, this is test.txt:
#echo off
echo Hello World! > CON
(for /L %a in (1,1,10) do (
echo Turn: %a
if %a equ 4 echo TURN NUMBER FOUR!
)) > CON
Output example:
C:\> cmd < test.txt > NUL
Hello World!
Turn: 1
Turn: 2
Turn: 3
Turn: 4
TURN NUMBER FOUR!
Turn: 5
Turn: 6
Turn: 7
Turn: 8
Turn: 9
Turn: 10
type some.txt>temp.bat
call temp.bat
del /q /f temp.bat
Is creating a temp file cheating?It's not mentioned as restriction in the question.Though you can loose the %ERRORLEVEL% because of the del command , but you can keep it in temp variable:
type some.txt>temp.bat
call temp.bat
set temp_el=%errorlevel%
del /q /f temp.bat
exit /b %temp_el%
I'm pretty sure you cannot do what you want. Windows will not let you configure the OS to recognize any other extensions as batch files. Only .bat and .cmd are supported.
You could process a series of simple commands within a text file using a FOR /F loop, but it will be very restrictive. For example, it will not support IF, FOR, GOTO Label, or CALL :Label. There are probably other restrictions. Within your main batch file, you could have the following:
for /f delims^=^ eol^= %%A in (script.txt) do %%A
You might be able to support IF and/or FOR if you execute the command via a new CMD.EXE shell, but then you cannot preserve the value of variables that might be SET by the command.
for /f delims^=^ eol^= %%A in (script.txt) do cmd /c "%%A"
See the windows shell commands
assoc. Associates a filename extension (e.g. *.txt) with a file type.
ftype. Lets you create a new file type that tells the windows shell how to open a particular kind of file.
From a command prompt, typing assoc /? or ftype /? will get you help on them. Or use your google-fu to find the MS docs.
*.bat is mapped to the file type batfile; *.cmd is mapped to the file type cmdfile. In windows 7 they are identical. If you want to be able to run files named *.foobar as a batch files, just type:
assoc .foobar=cmdfile
Then, assuming a file named 'sillyness.foobar' existing on the path, you just just type
c:\> sillyness
and it will find sillyness.foobar and execute it as a batch file. The Windows shell has a priority for how it resolves conflicts when you have files with the same name and different extensions (.com vs .cmd vs .bat, etc.)
Something like
assoc .pl=perlscript
ftype perlscript=perl.exe %1 %*
will set you up to run perl scripts as if they were .bat files.
If your batch commands are simple sequential ones then you could use this at the command prompt. Double the % signs for use in a batch file.
for /f "delims=" %a in (file.txt) do %a

What would be the Windows batch equivalent for HTML's input type="password"?

I need to get authentication credentials from the users within a Windows script but the classic "first Google result" approach:
SET /P USR=Username:
SET /P PWD=Password:
is less than satisfying, so I was wondering if there's let's say an "equivalent" to HTML's input type="password"?
Any comment would be really appreciated, thanks much in advance!
check out this
http://www.netikka.net/tsneti/info/tscmd052.htm
#echo off & setlocal enableextensions
:: Build a Visual Basic Script
set vbs_=%temp%\tmp$$$.vbs
set skip=
findstr "'%skip%VBS" "%~f0" > "%vbs_%"
::
:: Prompting without linefeed as in Item #15
echo.|set /p="Password: "
:: Run the script with Microsoft Windows Script Host Version 5.6
for /f "tokens=* delims=" %%a in ('cscript //nologo "%vbs_%"') do set MyPass1=%%a
::
::echo.
echo.|set /p="Retype : "
for /f "tokens=* delims=" %%a in ('cscript //nologo "%vbs_%"') do set MyPass2=%%a
::
:: Clean up
for %%f in ("%vbs_%") do if exist %%f del %%f
::
:: Demonstrate the result
echo.
if "%MyPass1%"=="%MyPass2%" (
echo The entered password was %MyPass1%
) else (
echo No match)
endlocal & goto :EOF
'
'The Visual Basic Script
Set WshPass = WScript.CreateObject("ScriptPW.Password") 'VBS
Password=WshPass.GetPassWord() 'VBS
WScript.Echo PassWord 'VBS
By judicious use of another tool freely available on Windows, the following two scripts do the job you want.
First, GetPwd.cmd:
#echo off
:: GetPwd.cmd - Get password with no echo.
<nul: set /p passwd=Password:
for /f "delims=" %%i in ('cscript /nologo GetPwd.vbs') do set passwd=%%i
echo.
:: This bit's just to prove we have the password.
echo %passwd%
Then, GetPwd.vbs:
' GetPwd.vbs - Get password with no echo then echo it. '
Set oScriptPW = CreateObject("ScriptPW.Password")
strPassword = oScriptPW.GetPassword()
Wscript.StdOut.WriteLine strPassword
Explanation:
GetPwd.vbs simply uses the password object to input the password from the user and then print it to standard output (next paragraph will explain why that doesn't show up in the terminal).
GetPwd.cmd is a bit trickier (but command scripts usually are).
The "<nul: set /p passwd=Password: " command simply outputs the prompt with no trailing CR/LF - it's a sneaky way to emulate bash's "echo -n". It sets passwd to an empty string as a side effect and doesn't wait for input since it's taking its input from the nul: device.
The "for /f "delims=" %%i in ('cscript /nologo GetPwd.vbs') do set passwd=%%i" statement is the trickiest bit. It runs the vbscript with no Microsoft advertising (/nologo), so that the only line output is the password (from the vbscript "Wscript.StdOut.WriteLine strPassword".
Setting the delimiters to nothing is required to capture input lines with spaces, otherwise you just get the first word. The "for ... do set ..." sets passwd to be the actual password output from the vbscript.
Then we echo a blank line (actually terminate the "Password: " line) and echo the password so you can verify it works:
C:\Pax> GetPwd
Password:
this is my password
C:\Pax>
The scriptpw.dll is available with XP and 2K3 but not necessarily later versions.
Instructions for Vista and presumably Win7 are below, give them a try:
To mask the password, the script takes advantage of the ScriptPW COM object. ScriptPW is loaded by default on Windows XP and Windows 2003. If you’re running Windows 2000 or Windows Vista, you will need to copy the scriptpw.dll file from the Windows\System32 folder of an XP system, or Windows 2003 system to the Winnt\System32 or Windows\System32 folder on your Windows 2000 or Vista system. Once the DLL has been copied, you will need to register it by running the command:
regsvr32 scriptpw.dll
To successfully register the DLL on a Vista machine, you will need to open the command prompt as administrator. To do this, click Start | All Programs | Accessories. Then right-click on the Command Prompt shortcut and select “Run as administrator.” Once at the command prompt as administrator, you’ll be able to successfully run the regsvr32 scriptpw.dll command to register the DLL.
1.Pure batch solution that (ab)uses XCOPY command and its /P /L switches found here :
:: Hidden.cmd
::Tom Lavedas, 02/05/2013, 02/20/2013
::Carlos, 02/22/2013
::https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/f7mb_f99lYI
#Echo Off
:HInput
SetLocal EnableExtensions EnableDelayedExpansion
Set "FILE=%Temp%.\T"
Set "FILE=.\T"
Keys List >"%File%"
Set /P "=Hidden text ending with Ctrl-C?: " <Nul
Echo.
Set "HInput="
:HInput_
For /F "tokens=1* delims=?" %%A In (
'"Xcopy /P /L "%FILE%" "%FILE%" 2>Nul"'
) Do (
Set "Text=%%B"
If Defined Text (
Set "Char=!Text:~1,1!"
Set "Intro=1"
For /F delims^=^ eol^= %%Z in ("!Char!") Do Set "Intro=0"
Rem If press Intro
If 1 Equ !Intro! Goto :HInput#
Set "HInput=!HInput!!Char!"
)
)
Goto :HInput_
:HInput#
Echo(!HInput!
Goto :Eof
2.Password submitter that uses a HTA pop-up
. This is a hybrit .bat/jscript/mshta file and should be saved as a .bat:
<!-- :
:: PasswordSubmitter.bat
#echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
set "pass=%%p"
)
echo your password is %pass%
exit /b
-->
<html>
<head><title>Password submitter</title></head>
<body>
<script language='javascript' >
function pipePass() {
var pass=document.getElementById('pass').value;
var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
close(fso.Write(pass));
}
</script>
<input type='password' name='pass' size='15'></input>
<hr>
<button onclick='pipePass()'>Submit</button>
</body>
</html>
3.A self-compiled .net hybrid .Again should be saved as .bat .In difference with other solutions it will create/compile a small .exe file that will be called (if you wish you can delete it). Also requires installed .net framework but that's rather not a problem:
#if (#X)==(#Y) #end /* JScript comment
#echo off
setlocal
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
set "jsc=%%v"
)
if not exist "%~n0.exe" (
"%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)
for /f "tokens=* delims=" %%p in ('"%~n0.exe"') do (
set "pass=%%p"
)
echo your password is %pass%
endlocal & exit /b %errorlevel%
*/
import System;
var pwd = "";
var key;
Console.Error.Write("Enter password: ");
do {
key = Console.ReadKey(true);
if ( (key.KeyChar.ToString().charCodeAt(0)) >= 20 && (key.KeyChar.ToString().charCodeAt(0) <= 126) ) {
pwd=pwd+(key.KeyChar.ToString());
Console.Error.Write("*");
}
} while (key.Key != ConsoleKey.Enter);
Console.Error.WriteLine();
Console.WriteLine(pwd);
I assume that you want no echo of the password on the screen.
If a pop-up window is ok for you, you could use e.g. VBScript to show an IE window displaying a password field. Here's an example.
As an alternative you could call your script from an HTA (HTML Application) file (see Introduction to HTML Applications (HTAs).
Regards,
divo
If you can install Cygwin, you'll get a bash shell by default, so this command will work:
read -s -p "Password: " PASSWORD
Only problem is now the value of PASSWORD is only set in the bash shell, not as an environment variable a batch file can see (don't use PWD as this means something else in cygwin). So you would have to rewrite your script as a bash shell script (maybe not too hard given the limitations of the command prompt!).
Or you could pass the password into a batch script from cygwin, but this means running a new instance of the command prompt:
cmd /cyourbatchfile.bat $PASSWORD
All a bit convoluted and not at all satisfying ;)
We do stuff like this all the time but put the password in the commandline and pass it to a variable in the batch file.
Another approach is to call PowerShell commands from your Batch script. Here's an example that configures the logon account of a service:
$password = Read-Host "Enter password" -AsSecureString;
$decodedpassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password));
& "sc.exe" config THE_SERVICE_NAME obj= THE_ACCOUNT password= $decodedPassword;
where THE_SERVICE_NAME is the name of the service to configure and THE_ACCOUNT is the logon account.
Then we can use it from a batch script like that:
call powershell -Command "$password = Read-Host "Enter password" -AsSecureString; $decodedpassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)); & "sc.exe" config THE_SERVICE_NAME obj= THE_ACCOUNT password= $decodedPassword;"
which is simply calling PowerShell.exe and passing the three commands.
The advantage of this approach is that the majority of Windows installations today include PowerShell, so no extra program or script is needed. The drawback is that you will need to either use the password inside the PowerShell call (like in my example) or store it in an environment variable and then use it from your batch script. I preffer the former because it is more secure and simpler.
You may use ReadFormattedLine subroutine for all kind of formatted input. For example, the commands below read an username and password of 8 characters each, display asterisks in the screen, and continue automatically with no need to press Enter:
call :ReadFormattedLine USR="********" /M "Username: "
call :ReadFormattedLine PWD="********" /M "Password: "
Or in a different way:
call :ReadFormattedLine nameAndPass="******** / ********" /M "Enter Username / Password: "
In previous example, when the user completed the username, the subroutine display the slash and read the password; if the user delete characters, the slash is also deleted automatically.
This subroutine is written in pure Batch so it does not require any additional program, and it allows several formatted input operations, like read just numbers, convert letters to uppercase, etc. You may download ReadFormattedLine subroutine from Read a line with specific format.
ConSet is a free tool written by Frank P. Westlake. It is an extended version of standard Windows command set.
ConSet.exe - Displays, sets, or deletes cmd.exe environment variables, modifies console parameters, and performs floating point mathematics.
As it is not a standard Windows console application, the usage of this tool requires either the distribution of this tool together with the batch file or the tool is stored on a server share and the batch file calls this tool directly from the server share.
ConSet makes a prompt for a password string with hidden input assigned to an environment variable very easy:
ConSet.exe /PH "PWD=Password: "
The additional parameter H results in hiding user input.
I wrote an open-source tool called editenv that replaces my older editv32/editv64 utilities:
https://github.com/Bill-Stewart/editenv
It provides the --maskinput (-m) option[*] that lets you hide the typed input. Example:
editenv --maskinput --prompt="Password: " PWD
This command displays a Password: prompt, and whatever you enter is placed in the PWD environment variable.
Download here:
https://github.com/Bill-Stewart/editenv/releases
[*] Note that the --maskinput (-m) option is not secure -- typed input is placed in plain-text in the environment. This feature is for convenience only.
Original poster asked for a DOS BATCH solution that allows for input of a password without printing it on the screen. All solutions so far use some external script, VBA, Powershell, Cygwin, whatever. To me, none of these are a nice, clean and simple.
In my case, I will go the python route. A DOS BAT script can easily be replaced by a simple python script. In python, the password entry problem is trivially solved with import getpass; password = getpass.getpass() . Then, python is a lightweight and reliable extension to your windows pc, and the script may be portable to other OS's (linux, mac). In my case, I need a startup script for Pentaho, a tool that is available for windows and linux.
This issue makes you wonder why write scripts in BAT or even BASH. Is powershell really an improvement on BAT, and does python perhaps solve problems in all of these systems?
This also makes you wonder how Powershell could miss the boat here. Why is the python call not also in Powershell, there is no licensing issue??? The "not invented here" syndrome?
Of course, there will be very simple situations where a BAT (or BASH) script is the easiest way, or where Powershell is required, but otherwise I'd go for python.

Resources