我可以在 bat 文件中屏蔽输入文本吗?

我正在编写一个批处理文件来执行其他一些程序。在这种情况下,我需要提示输入密码。我有没有办法屏蔽输入文本?我不需要打印字符而不是输入字符。Linux 的密码提示行为(输入时不打印任何内容)就足够了。

@echo off
SET /P variable=Password :
echo %variable%
Pause

这将读取输入,但是我不能使用这种方法屏蔽文本。

240053 次浏览

I would probably just do:

..
echo Before you enter your password, make sure no-one is looking!
set /P password=Password:
cls
echo Thanks, got that.
..

So you get a prompt, then the screen clears after it's entered.

Note that the entered password will be stored in the CMD history if the batch file is executed from a command prompt (Thanks @Mark K Cowan).

If that wasn't good enough, I would either switch to python, or write an executable instead of a script.

I know none of these are perfect soutions, but maybe one is good enough for you :)

Up to XP and Server 2003, you can make use of another included tool (VBScript) - the following two scripts do the job you want.

First, getpwd.cmd:

@echo off
<nul: set /p passwd=Password:
for /f "delims=" %%i in ('cscript /nologo getpwd.vbs') do set passwd=%%i
echo.

Then, getpwd.vbs:

Set oScriptPW = CreateObject("ScriptPW.Password")
strPassword = oScriptPW.GetPassword()
Wscript.StdOut.WriteLine strPassword

The getpwd.vbs simply uses the password object to input the password from the user and then print it to standard output (the next paragraph will explain why that doesn't show up in the terminal).

The getpwd.cmd command script is a bit trickier but it basically works as follows.

The effect of the "<nul: set /p passwd=Password: " command is to output the prompt with no trailing newline character - it's a sneaky way to emulate the "echo -n" command from the bash shell. It sets passwd to an empty string as an irrelevant 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", 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 an entire input line with spaces, otherwise you just get the first word. The "for ... do set ..." bit sets passwd to be the actual password output from the VBScript.

Then we echo a blank line (to terminate the "Password: " line) and the password will be in the passwd environment variable after the code has run.


Now, as mentioned, scriptpw.dll is available only up to XP/2003. In order to rectify this, you can simply copy the scriptpw.dll file from the Windows\System32 folder of an XP/2003 system to the Winnt\System32 or Windows\System32 folder on your own system. Once the DLL has been copied, you will need to register it by running:

regsvr32 scriptpw.dll

To successfully register the DLL on Vista and later, you will need administrator privileges. I haven't examined the legality of such a move so cave lector.


If you're not overly keen on trying to track down and register older DLL files (for convenience or legal reasons), there is another way. Later versions of Windows (the ones that don't have the required DLL) should have Powershell available to you.

And, in fact, you really should consider upgrading your scripts to use it fully since it's a much more capable scripting language than cmd.exe. However, if you want to keep the bulk of your code as cmd.exe scripts (such as if you have a lot of code that you don't want to convert), you can use the same trick.

First, modify the cmd script so it calls Powershell rather than CScript:

@echo off
for /f "delims=" %%i in ('powershell -file getpwd.ps1') do set passwd=%%i

The Powershell script is equally simple:

$password = Read-Host "Enter password" -AsSecureString
$password = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$password = [Runtime.InteropServices.Marshal]::PtrToStringAuto($password)
echo $password

although with some marshalling to get the actual password text.

Remember that, to run local unsigned Powershell scripts on your machine, you may need to modify the execution policy from the (draconian, though very safe) default, with something like:

set-executionpolicy remotesigned

from within Powershell itself.

another alternative is my EditV32 (x86) or EditV64 (x64) command-line tools. For example:

editv32 -m -p "Password: " PWD

-m means "masked input" and -p is the prompt. The user's input is stored in the PWD environment variable. You can get it here:

https://westmesatech.com/?page_id=19

I read all the clunky solutions on the net about how to mask passwords in a batch file, the ones from using a hide.com solution and even the ones that make the text and the background the same color. The hide.com solution works decent, it isn't very secure, and it doesn't work in 64-bit Windows. So anyway, using 100% Microsoft utilities, there is a way!

First, let me explain my use. I have about 20 workstations that auto logon to Windows. They have one shortcut on their desktop - to a clinical application. The machines are locked down, they can't right click, they can't do anything but access the one shortcut on their desktop. Sometimes it is necessary for a technician to kick up some debug applications, browse windows explorer and look at log files without logging the autolog user account off.

So here is what I have done.

Do it however you wish, but I put my two batch files on a network share that the locked down computer has access to.

My solution utilizes 1 main component of Windows - runas. Put a shortcut on the clients to the runas.bat you are about to create. FYI, on my clients I renamed the shortcut for better viewing purposes and changed the icon.

You will need to create two batch files.

I named the batch files runas.bat and Debug Support.bat

runas.bat contains the following code:

cls
@echo off
TITLE CHECK CREDENTIALS
goto menu


:menu
cls
echo.
echo           ....................................
echo            ~Written by Cajun Wonder 4/1/2010~
echo           ....................................
echo.
@set /p un=What is your domain username?
if "%un%"=="PUT-YOUR-DOMAIN-USERNAME-HERE" goto debugsupport
if not "%un%"=="PUT-YOUR-DOMAIN-USERNAME-HERE" goto noaccess
echo.
:debugsupport
"%SYSTEMROOT%\system32\runas" /netonly /user:PUT-YOUR-DOMAIN-NAME-HERE\%un% "\\PUT-YOUR-NETWORK-SHARE-PATH-HERE\Debug Support.bat"
@echo ACCESS GRANTED! LAUNCHING THE DEBUG UTILITIES....
@ping -n 4 127.0.0.1 > NUL
goto quit
:noaccess
cls
@echo.
@echo.
@echo.
@echo.
@echo   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
@echo   \\                                   \\
@echo   \\    Insufficient privileges         \\
@echo   \\                                    \\
@echo   \\      Call Cajun Wonder             \\
@echo   \\                                    \\
@echo   \\              At                    \\
@echo   \\                                    \\
@echo   \\        555-555-5555                \\
@echo   \\                                    \\
@echo   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
@ping -n 4 127.0.0.1 > NUL
goto quit
@pause
:quit
@exit

You can add as many if "%un%" and if not "%un%" for all the users you want to give access to. The @ping is my coonass way of making a seconds timer.

So that takes care of the first batch file - pretty simple eh?

Here is the code for Debug Support.bat:

cls
@echo off
TITLE SUPPORT UTILITIES
goto menu


:menu
cls
@echo %username%
echo.
echo           .....................................
echo            ~Written by Cajun Wonder 4/1/2010~
echo           .....................................
echo.
echo What do you want to do?
echo.
echo [1]  Launch notepad
echo.


:choice
set /P C=[Option]?
if "%C%"=="1" goto notepad
goto choice


:notepad
echo.
@echo starting notepad....
@ping -n 3 127.0.0.1 > NUL
start notepad
cls
goto menu

I'm not a coder and really just started getting into batch scripting about a year ago, and this round about way that I discovered of masking a password in a batch file is pretty awesome!

I hope to hear that someone other than me is able to get some use out of it!

I used Blorgbeard's above solution which is actually great in my opinion. Then I enhanced it as follows:

  1. Google for ansicon
  2. Download zip file and sample text file.
  3. Install (that means copy 2 files into system32)

Use it like this:

@echo off
ansicon -p
set /p pwd=Password:ESC[0;37;47m
echo ESC[0m

This switches the console to gray on gray for your password entry and switches back when you are done. The ESC should actually be an unprintable character, which you can copy over from the downloaded sample text file (appears like a left-arrow in Notepad) into your batch file. You can use the sample text file to find the codes for all color combinations.

If you are not admin of the machine, you will probably be able to install the files in a non-system directory, then you have to append the directory to the PATH in your script before calling the program and using the escape sequences. This could even be the current directory probably, if you need a non-admin distributable package of just a few files.

make a batch file that calls the one needed for invisible characters then make a shortcut for the batch file being called.

right click

properties

colors

text==black

background == black

apply

ok

hope thus helps you!!!!!!!!

This may be an older topic, but if you are using Windows Vista or 7, I have a solution that will work very well. I made a video of it here: http://www.youtube.com/watch?v=mk8uAa6PIFM

Pastebin for the batch file is here

Yes - I am 4 years late.

But I found a way to do this in one line without having to create an external script; by calling powershell commands from a batch file.

Thanks to TessellatingHeckler - without outputting to a text file (I set the powershell command in a variable, because it's pretty messy in one long line inside a for loop).

@echo off
set "psCommand=powershell -Command "$pword = read-host 'Enter Password' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set password=%%p
echo %password%

Originally I wrote it to output to a text file, then read from that text file. But the above method is better. In one extremely long, near incomprehensible line:

@echo off
powershell -Command $pword = read-host "Enter password" -AsSecureString ; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword) ; [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) > .tmp.txt & set /p password=<.tmp.txt & del .tmp.txt
echo %password%

I'll break this down - you can split it up over a few lines using caret ^, which is much nicer...

@echo off
powershell -Command $pword = read-host "Enter password" -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword) ; ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) > .tmp.txt
set /p password=<.tmp.txt & del .tmp.txt
echo %password%

This article explains what the powershell commands are doing; essentially it gets input using Read-Host -AsSecureString - the following two lines convert that secure string back into plain text, the output (plaintext password) is then sent to a text file using >.tmp.txt. That file is then read into a variable and deleted.

If the lack of source code bothers you, I have another alternative.

@echo off
for /f "delims=" %%p in ('ReadLine -h -p "Enter password: "') do set PWD=%%p
echo You entered: %PWD%

You can get it from https://westmesatech.com/?page_id=49. Source code is included.

1.Pure batch solution that (ab)uses XCOPY command and its /P /L switches found here (some improvements on this could be 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

1.2 Another way based on replace command

@Echo Off
SetLocal EnableExtensions EnableDelayedExpansion


Set /P "=Enter a Password:" < Nul
Call :PasswordInput
Echo(Your input was:!Line!


Goto :Eof


:PasswordInput
::Author: Carlos Montiers Aguilera
::Last updated: 20150401. Created: 20150401.
::Set in variable Line a input password
For /F skip^=1^ delims^=^ eol^= %%# in (
'"Echo(|Replace.exe "%~f0" . /U /W"') Do Set "CR=%%#"
For /F %%# In (
'"Prompt $H &For %%_ In (_) Do Rem"') Do Set "BS=%%#"
Set "Line="
:_PasswordInput_Kbd
Set "CHR=" & For /F skip^=1^ delims^=^ eol^= %%# in (
'Replace.exe "%~f0" . /U /W') Do Set "CHR=%%#"
If !CHR!==!CR! Echo(&Goto :Eof
If !CHR!==!BS! (If Defined Line (Set /P "=!BS! !BS!" <Nul
Set "Line=!Line:~0,-1!"
)
) Else (Set /P "=*" <Nul
If !CHR!==! (Set "Line=!Line!^!"
) Else Set "Line=!Line!!CHR!"
)
Goto :_PasswordInput_Kbd

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' >
window.resizeTo(300,150);
function entperPressed(e){
if (e.keyCode == 13) {
pipePass();
}
}
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' onkeypress="return entperPressed(event)" ></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 enableDelayedExpansion


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("*");
}


if ( key.Key == ConsoleKey.Backspace && pwd.Length > 0 ) {
pwd=pwd.Remove(pwd.Length-1);
Console.Error.Write("\b \b");
}




} while (key.Key != ConsoleKey.Enter);
Console.Error.WriteLine();
Console.WriteLine(pwd);

You may use ReadFormattedLine subroutine for all kind of formatted input. For example, the command below read a password of 8 characters, display asterisks in the screen, and continue automatically with no need to press Enter:

call :ReadFormattedLine password="********" /M "Enter password (8 chars): "

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.


EDIT 2018-08-18: New method to enter an "invisible" password

The FINDSTR command have a strange bug that happen when this command is used to show characters in color AND the output of such a command is redirected to CON device. For details on how use FINDSTR command to show text in color, see this topic.

When the output of this form of FINDSTR command is redirected to CON, something strange happens after the text is output in the desired color: all the text after it is output as "invisible" characters, although a more precise description is that the text is output as black text over black background. The original text will appear if you use COLOR command to reset the foreground and background colors of the entire screen. However, when the text is "invisible" we could execute a SET /P command, so all characters entered will not appear on the screen.

@echo off
setlocal


set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"

UPDATE:
I added two new methods that instead of utilizing cls to hide the input they create a new pop-up with one line only.

The drawbacks are that one method (method 2) leaves junk in the registry - "If run without proper rights", and the other one (method three) appends some junk to the script. Needless to say that it can easily be written to any tmp file and deleted I just tried to come up with an alternative.

Limitation: The password can only be alphanumeric - no other characters!

@echo off
if "%1"=="method%choice%" goto :method%choice%
::::::::::::::::::
::Your code here::
::::::::::::::::::
cls
echo :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
echo ::::                   Batch script to prompt for password!                 :::
echo :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:choice
echo.
echo 1. First method
echo.
echo 2. Second method
echo.
echo 3. Third method
echo.
set/p choice=Choose a method:
if "%choice%" gtr "3" echo. & echo invalid option & echo. & pause & goto choice


call :vars
set options= %num%%smAlph%%cpAlph%
set pwdLen=6


if "%choice%" == "1" (
set /p=Password: <nul
for /l %%i in (1,1,%pwdLen%) do call :password
) else (
start /wait cmd /c call "%~f0" method%choice%
)


call :result%choice%




::just to see if it worked!
echo.
echo The Password you entered is: "%pwd%"&pause>nul


::::::::::::::::::
::More code here::
::::::::::::::::::
exit /b










:vars
set num=1234567890
set smAlph=abcdefghijklmnopqrstuvwxyz
set cpAlph=ABCDEFGHIJKLMNOPQRSTUVWXYZ
set pwd=
goto :EOF




:method2
call :popUp
setx result %pwd% >nul
goto :EOF


:method3
call :popUp
>> "%~f0" echo.
>> "%~f0" echo :result%choice%
>> "%~f0" echo set pwd=%pwd%
goto :EOF


:popUp
title Password
mode con lines=1 cols=30
color 5a
set /p=Password: <nul
for /l %%i in (1,1,%pwdLen%) do call :password
goto :EOF


:password
:: If you don't want case sensative remove "/cs" but remember to remove %cpAlph% from the %options%
choice /c %options% /n /cs >nul
call SET pwd=%pwd%%%options:~%errorlevel%,1%%
set /p =*<nul
GOTO :EOF




:result2
for /f "tokens=3" %%a in ('reg query hkcu\environment /v result') do set pwd=%%a
setx result "" >nul
reg delete hkcu\environment /v result /f >nul 2>&1
:result1
goto :EOF
::You can delete from here whenever you want.

Update: I found sachadee's post to be perfect and I just added my "pop-up" quirk to it.

@Echo Off
SetLocal EnableDelayedExpansion
if "%1"==":HInput" goto :HInput
set r=r%random%
start /wait cmd /c call "%~f0" :HInput


For /f "tokens=2,13 delims=, " %%a in (
'tasklist /v /fo csv /fi "imagename eq cmd.exe"
^|findstr /v "Windows\\system32\\cmd.exe"
^|findstr "set /p=%r%"'
) do (
set pid=%%a
set Line=%%b
set Line=!Line:%r%=!
set Line=!Line:~,-2!
)
taskkill /pid %pid:"=%>nul
goto :HIEnd




:HInput
SetLocal DisableDelayedExpansion
title Password
mode con lines=2 cols=30


Echo Enter your Code :
Set "Line="
For /F %%# In (
'"Prompt;$H&For %%# in (1) Do Rem"'
) Do Set "BS=%%#"


:HILoop
Set "Key="
For /F "delims=" %%# In (
'Xcopy /W "%~f0" "%~f0" 2^>Nul'
) Do If Not Defined Key Set "Key=%%#"
Set "Key=%Key:~-1%"
SetLocal EnableDelayedExpansion
If Not Defined Key start /min cmd /k mode con lines=1 cols=14 ^&set/p %r%!Line!=&exit
If %BS%==^%Key% (Set /P "=%BS% %BS%" <Nul
Set "Key="
If Defined Line Set "Line=!Line:~0,-1!"
) Else Set /P "=*" <Nul
If Not Defined Line (EndLocal &Set "Line=%Key%"
) Else For /F delims^=^ eol^= %%# In (
"!Line!") Do EndLocal &Set "Line=%%#%Key%"
Goto :HILoop


:HIEnd
Echo(
Echo Your code is :  "!Line!"
Pause
Goto :Eof
@echo off
color 0f
MODE CON COLS=132 LINES=50
:start
cls
choice /C ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!?.# /N /CS /M Please enter your password to continue. (Valid characters include all letters, numbers, and ! ? .) Press # to submit:
SET ecode=%ERRORLEVEL%
IF %ecode% EQU 66 goto submit
IF %ecode% EQU 1 SET out=A
IF %ecode% EQU 2 SET out=B
IF %ecode% EQU 3 SET out=C
IF %ecode% EQU 4 SET out=D
IF %ecode% EQU 5 SET out=E
IF %ecode% EQU 6 SET out=F
IF %ecode% EQU 7 SET out=G
IF %ecode% EQU 8 SET out=H
IF %ecode% EQU 9 SET out=I
IF %ecode% EQU 10 SET out=J
IF %ecode% EQU 11 SET out=K
IF %ecode% EQU 12 SET out=L
IF %ecode% EQU 13 SET out=M
IF %ecode% EQU 14 SET out=N
IF %ecode% EQU 15 SET out=O
IF %ecode% EQU 16 SET out=P
IF %ecode% EQU 17 SET out=Q
IF %ecode% EQU 18 SET out=R
IF %ecode% EQU 19 SET out=S
IF %ecode% EQU 20 SET out=T
IF %ecode% EQU 21 SET out=U
IF %ecode% EQU 22 SET out=V
IF %ecode% EQU 23 SET out=W
IF %ecode% EQU 24 SET out=X
IF %ecode% EQU 25 SET out=Y
IF %ecode% EQU 26 SET out=Z
IF %ecode% EQU 27 SET out=a
IF %ecode% EQU 28 SET out=b
IF %ecode% EQU 29 SET out=c
IF %ecode% EQU 30 SET out=d
IF %ecode% EQU 31 SET out=e
IF %ecode% EQU 32 SET out=f
IF %ecode% EQU 33 SET out=g
IF %ecode% EQU 34 SET out=h
IF %ecode% EQU 35 SET out=i
IF %ecode% EQU 36 SET out=j
IF %ecode% EQU 37 SET out=k
IF %ecode% EQU 38 SET out=l
IF %ecode% EQU 39 SET out=m
IF %ecode% EQU 40 SET out=n
IF %ecode% EQU 41 SET out=o
IF %ecode% EQU 42 SET out=p
IF %ecode% EQU 43 SET out=q
IF %ecode% EQU 44 SET out=r
IF %ecode% EQU 45 SET out=s
IF %ecode% EQU 46 SET out=t
IF %ecode% EQU 47 SET out=u
IF %ecode% EQU 48 SET out=v
IF %ecode% EQU 49 SET out=w
IF %ecode% EQU 50 SET out=x
IF %ecode% EQU 51 SET out=y
IF %ecode% EQU 52 SET out=z
IF %ecode% EQU 53 SET out=0
IF %ecode% EQU 54 SET out=1
IF %ecode% EQU 55 SET out=2
IF %ecode% EQU 56 SET out=3
IF %ecode% EQU 57 SET out=4
IF %ecode% EQU 58 SET out=5
IF %ecode% EQU 59 SET out=6
IF %ecode% EQU 60 SET out=7
IF %ecode% EQU 61 SET out=8
IF %ecode% EQU 62 SET out=9
IF %ecode% EQU 63 SET out=!
IF %ecode% EQU 64 SET out=?
IF %ecode% EQU 65 SET out=.
SET code=%out%
SET show=*
:loop
cls
choice /C ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!?.# /N /CS /M Please enter your password to continue. (Valid characters include all letters, numbers, and ! ? .) Press # to submit: %code%
SET ecode=%ERRORLEVEL%
IF %ecode% EQU 66 goto submit
IF %ecode% EQU 1 SET out=A
IF %ecode% EQU 2 SET out=B
IF %ecode% EQU 3 SET out=C
IF %ecode% EQU 4 SET out=D
IF %ecode% EQU 5 SET out=E
IF %ecode% EQU 6 SET out=F
IF %ecode% EQU 7 SET out=G
IF %ecode% EQU 8 SET out=H
IF %ecode% EQU 9 SET out=I
IF %ecode% EQU 10 SET out=J
IF %ecode% EQU 11 SET out=K
IF %ecode% EQU 12 SET out=L
IF %ecode% EQU 13 SET out=M
IF %ecode% EQU 14 SET out=N
IF %ecode% EQU 15 SET out=O
IF %ecode% EQU 16 SET out=P
IF %ecode% EQU 17 SET out=Q
IF %ecode% EQU 18 SET out=R
IF %ecode% EQU 19 SET out=S
IF %ecode% EQU 20 SET out=T
IF %ecode% EQU 21 SET out=U
IF %ecode% EQU 22 SET out=V
IF %ecode% EQU 23 SET out=W
IF %ecode% EQU 24 SET out=X
IF %ecode% EQU 25 SET out=Y
IF %ecode% EQU 26 SET out=Z
IF %ecode% EQU 27 SET out=a
IF %ecode% EQU 28 SET out=b
IF %ecode% EQU 29 SET out=c
IF %ecode% EQU 30 SET out=d
IF %ecode% EQU 31 SET out=e
IF %ecode% EQU 32 SET out=f
IF %ecode% EQU 33 SET out=g
IF %ecode% EQU 34 SET out=h
IF %ecode% EQU 35 SET out=i
IF %ecode% EQU 36 SET out=j
IF %ecode% EQU 37 SET out=k
IF %ecode% EQU 38 SET out=l
IF %ecode% EQU 39 SET out=m
IF %ecode% EQU 40 SET out=n
IF %ecode% EQU 41 SET out=o
IF %ecode% EQU 42 SET out=p
IF %ecode% EQU 43 SET out=q
IF %ecode% EQU 44 SET out=r
IF %ecode% EQU 45 SET out=s
IF %ecode% EQU 46 SET out=t
IF %ecode% EQU 47 SET out=u
IF %ecode% EQU 48 SET out=v
IF %ecode% EQU 49 SET out=w
IF %ecode% EQU 50 SET out=x
IF %ecode% EQU 51 SET out=y
IF %ecode% EQU 52 SET out=z
IF %ecode% EQU 53 SET out=0
IF %ecode% EQU 54 SET out=1
IF %ecode% EQU 55 SET out=2
IF %ecode% EQU 56 SET out=3
IF %ecode% EQU 57 SET out=4
IF %ecode% EQU 58 SET out=5
IF %ecode% EQU 59 SET out=6
IF %ecode% EQU 60 SET out=7
IF %ecode% EQU 61 SET out=8
IF %ecode% EQU 62 SET out=9
IF %ecode% EQU 63 SET out=!
IF %ecode% EQU 64 SET out=?
IF %ecode% EQU 65 SET out=.
SET code=%code%%out%
SET show=%show%*
goto loop
:submit
cls
SET password=%code%
IF %password% EQU 0cZrocks! SET result=1
IF ELSE SET result=2
IF %result% EQU 1 echo password correct
IF %result% EQU 2 echo password incorrect
timeout /T 2 /NOBREAK >nul
cls
IF %result% EQU 1 goto end
IF ELSE goto start
:end

If you have Python installed, you can use:

for /f "delims=" %%A in ('python -c "import getpass; print(getpass.getpass('Enter the CVS password: '));"') do @set CVSPASS=%%A
echo PASS: %CVSPASS%

the output:

Enter the CVS password:
PASS: 123

I wrote an open source program called editenv that replaces my older editv32/editv64 utilities:

https://github.com/Bill-Stewart/editenv

The --maskinput (-m) option[*] lets you hide (mask) the typed input and has a configurable character (default character is *); e.g.:

editenv -m -p "Password: " PWD

The --prompt (-p) option lets you specify an input prompt. The above will display a Password: prompt and wait for you to enter something. Typed characters will appear as *. Pressing Ctrl+C will end the program with an exit code of 1223.

Download is here:

https://github.com/Bill-Stewart/editenv/releases

[*] Note that the --maskinput (-m) option is not secure -- the entered string is entered as plain-text in the environment. This feature is for convenience only.

You can set the forground color to black such:

:: see https://stackoverflow.com/questions/33293220/what-is-the-fastest-color-function-in-batch
@echo off
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
set color_white=%ESC%[37m
set color_black=%ESC%[30m
echo(
set /p user=Username:
set /p pass=password:%color_black%
echo %color_white%
echo blablablba

Enjoy!!! C.

Ok so I just found a really decent work around to this issue. CMDKEY works on windows 7+ and allows you to enter details into the windows cred manager from the cmd prompt, and if you use the /pass switch it provides its own password entry without exposing the password. It does not present ***** as you type but the password is hidden.

The script below requests the username as normal and creates a var called "%username%" it then checks to see if the cred manager already has an entry for the target server. If it does it just maps the drive to the usename and does not request a password. If there is no entry it then uses the CMDKEY to prompt for password and stores it in cred manager.

    set /p username="Enter School Username: "
CMDKEY /list:SERVERNAME | FIND "NONE" > nul 2>&1
IF %ERRORLEVEL% NEQ 0 GOTO MAPDRIVES
CMDKEY /ADD:SERVERNAME /username:%username% /pass
:MAPDRIVES
NET USE Y: \\SERVERNAME\SHARE\%username%

I couldn't get @unclemeat's answer to work on Windows 10 21H1 systems unfortunately. I just got: [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)"" was unexpected at this time.

But he set me on the right track.

So here is my variant:

Configuration at top of script:

@ECHO OFF
:: Don't leak variables to command shell
SETLOCAL


REM service user for backend services - comment out to default to LOCALSYSTEM
SET WINDOWS_SVC_USERNAME=svcadmin

Somewhere at the bottom after checking for admin privileges and after creating the service:

SETLOCAL ENABLEDELAYEDEXPANSION


:: Read password for service user
IF DEFINED WINDOWS_SVC_USERNAME (
SET PWR=powershell -Command "$secureString = Read-Host 'Enter password for service user \".\%WINDOWS_SVC_USERNAME%\"' -AsSecureString -ErrorAction Stop; $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($secureString); $plain = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr); [System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($ptr); Write-Host $plain;"
FOR /F "usebackq delims=" %%P IN (`!PWR!`) DO SET WINDOWS_SVC_PASSWORD=%%P
IF DEFINED WINDOWS_SVC_PASSWORD (
IF ["!WINDOWS_SVC_PASSWORD!"] NEQ [""] (
IF ["!WINDOWS_SVC_PASSWORD!"] NEQ [" "] (
:: The password is now set correctly
ECHO "Using ".\%WINDOWS_SVC_USERNAME%" as service user..."
sc config  prod!WINDOWS_SVC_INFIX!rest!INDEX! obj= ".\!WINDOWS_SVC_USERNAME!" password= "!WINDOWS_SVC_PASSWORD!"
) ELSE (
ECHO "ERROR -- Password possibly empty or PowerShell threw an exception."
SET "WINDOWS_SVC_USERNAME="
)
) ELSE (
ECHO "ERROR -- Could not retrieve password! Password is possibly empty."
SET "WINDOWS_SVC_USERNAME="
)
) ELSE (
ECHO "ERROR -- No password given or PowerShell is not available."
SET "WINDOWS_SVC_USERNAME="
)
) ELSE (
ECHO "No service user specified - keeping default "LOCALSYSTEM" user..."
)

Of course the sc config prod!WINDOWS_SVC_INFIX!rest!INDEX! is just copied from my for-loop further down and needs adaption to your specific case. Use ECHO password read: "!WINDOWS_SVC_PASSWORD!" for debugging instead.

This is not yet tested in the wild, so please handle with care.