web-dev-qa-db-fra.com

Puis-je masquer un texte d'entrée dans un fichier bat

J'écris un fichier batch pour exécuter d'autres programmes. Dans ce cas, je dois demander un mot de passe. Ai-je un moyen de masquer le texte saisi? Je n'ai pas besoin d'imprimer des caractères ******* à la place des caractères saisis. Le comportement d'invite de mot de passe de Linux (ne rien imprimer lors de la frappe) suffit.

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

Cela lira l'entrée mais je ne peux pas masquer le texte en utilisant cette approche.

Jusqu'à XP et Server 2003, vous pouvez utiliser un autre outil inclus (VBScript) - les deux scripts suivants effectuent le travail souhaité.

D'abord, getpwd.cmd:

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

Ensuite, getpwd.vbs:

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

Le getpwd.vbs Utilise simplement l'objet mot de passe pour entrer le mot de passe de l'utilisateur, puis l'imprimer sur la sortie standard (le paragraphe suivant expliquera pourquoi cela n'apparaît pas dans le terminal).

Le script de commande getpwd.cmd Est un peu plus compliqué, mais il fonctionne comme suit.

L'effet de la commande "<nul: set /p passwd=Password: " Est de générer l'invite sans caractère de fin de ligne - c'est une manière sournoise d'émuler la commande "echo -n" À partir du shell bash. Il définit passwd sur une chaîne vide en tant qu'effet secondaire non pertinent et n'attend pas l'entrée, car il tire son entrée du périphérique nul:.

L'instruction "for /f "delims=" %%i in ('cscript /nologo getpwd.vbs') do set passwd=%%i" est le bit le plus compliqué. Il exécute le script VBScript sans "publicité" de Microsoft, de sorte que la seule sortie en ligne est le mot de passe (du script VB "Wscript.StdOut.WriteLine strPassword".

Il est nécessaire de définir les délimiteurs sur rien pour capturer une ligne d'entrée entière avec des espaces, sinon vous obtenez uniquement le premier mot. Le bit "for ... do set ..." Définit passwd comme le mot de passe réel généré par le script VBScript.

Ensuite, nous renvoyons une ligne vierge (pour mettre fin à la ligne "Password: ") Et le mot de passe sera dans la variable d'environnement passwd après l'exécution du code.


Maintenant, comme mentionné, scriptpw.dll Est disponible uniquement jusqu'à XP/2003. Pour remédier à cela, il vous suffit de copier le fichier scriptpw.dll Du dossier Windows\System32 D’un système XP/2003 dans le dossier Winnt\System32 Ou Windows\System32 Situé sur votre propre système. Une fois que la DLL a été copiée, vous devrez l'enregistrer en lançant:

regsvr32 scriptpw.dll

Pour enregistrer avec succès la DLL sur Vista et ultérieur, vous aurez besoin de privilèges d’administrateur. Je n’ai pas examiné la légalité d’un tel déménagement, mais cédez-vous au lecteur.


Si vous n'êtes pas excessivement désireux d'essayer de localiser et d'enregistrer des fichiers plus anciens DLL (pour des raisons pratiques ou légales)), il existe un autre moyen. Versions ultérieures de Windows (ceux qui ne sont pas ont la DLL requise) devrait avoir Powershell à votre disposition.

Et, en fait, vous devriez vraiment envisager de mettre à niveau vos scripts afin de les utiliser pleinement, car il s'agit d'un langage de script beaucoup plus performant que cmd.exe. Cependant, si vous souhaitez conserver la majeure partie de votre code sous forme de scripts cmd.exe (Par exemple, si vous avez un lot de code que vous ne souhaitez pas convertir), vous pouvez utiliser le même truc.

Commencez par modifier le script cmd afin qu’il appelle Powershell plutôt que CScript:

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

Le script Powershell est également simple:

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

bien qu'avec un peu de marshalling pour obtenir le texte du mot de passe réel.

N'oubliez pas que, pour exécuter des scripts Powershell locaux non signés sur votre ordinateur, vous devrez peut-être modifier la stratégie d'exécution à partir de la valeur par défaut (draconienne, mais très sûre), avec quelque chose comme:

set-executionpolicy remotesigned

de l'intérieur de Powershell lui-même.

49
paxdiablo

Oui, j'ai 4 ans de retard.

Mais j'ai trouvé un moyen de faire cela en une ligne sans avoir à créer un script externe; en appelant des commandes powershell à partir d'un fichier de commandes.

Grâce à TessellatingHeckler - sans sortie dans un fichier texte (je règle la commande powershell dans une variable, car elle est assez compliquée dans une longue ligne dans une boucle for).

@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%

Au départ, je l’écrivais dans un fichier texte, puis lu à partir de ce fichier texte. Mais la méthode ci-dessus est meilleure. Dans une ligne extrêmement longue et presque incompréhensible:

@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%

Je vais décomposer cela - vous pouvez le diviser en quelques lignes en utilisant caret ^, qui est beaucoup plus agréable ...

@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%

Cet article explique ce que font les commandes powershell; essentiellement, il obtient une entrée en utilisant Read-Host -AsSecureString - Les deux lignes suivantes convertissent cette chaîne sécurisée en texte brut. La sortie (mot de passe en texte brut) est ensuite envoyée à un fichier texte à l'aide de >.tmp.txt. Ce fichier est ensuite lu dans une variable et supprimé.

143
unclemeat

1. Solution par lots pure qui (ab) utilise XCOPY commande et ses /P /L commutateurs trouvés ici (quelques améliorations à ce sujet pourraient se trouve ici ):

:: 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 Autre méthode basée sur la commande de remplacement

@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. Émetteur de mots de passe utilisant un pop-up HTA . Ceci est un fichier hybride .bat/jscript/mshta et doit être enregistré en tant que . 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 . n hybride .net auto-compilé .Again doit être enregistré sous le format .bat . À la différence d’autres solutions, il crée/compile un petit fichier .exe qui sera appelé (si vous le souhaitez, vous pouvez le supprimer). Nécessite également une structure .net installée, mais ce n'est pas un problème:

@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);
23
npocmaka

Je ferais probablement juste:

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

Ainsi, vous obtenez une invite, puis l'écran s'efface une fois entré.

Notez que le mot de passe saisi sera stocké dans l'historique CMD si le fichier de commandes est exécuté à partir d'une invite de commande (Merci @ Mark K Cowan ).

Si cela ne suffisait pas, je devrais soit passer à python, soit écrire un exécutable au lieu d'un script.

Je sais qu'aucune d'elles n'est parfaite, mais peut-être une suffirait-elle pour vous :)

12
Blorgbeard

une autre alternative est mes outils de ligne de commande EditV32 (x86) ou EditV64 (x64). Par exemple:

editv32 -m -p "Password: " PWD

-m signifie "entrée masquée" et -p est l'invite. L'entrée de l'utilisateur est stockée dans la variable d'environnement PWD. Vous pouvez l'obtenir ici:

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

6
Bill_Stewart

Si le manque de code source vous dérange, j'ai une autre alternative.

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

Vous pouvez l'obtenir de https://westmesatech.com/?page_id=49 . Le code source est inclus.

5
Bill_Stewart

Vous pouvez utiliser le sous-programme ReadFormattedLine pour tout type d’entrée formatée. Par exemple, la commande ci-dessous lit un mot de passe de 8 caractères, affiche des astérisques à l'écran et poursuit automatiquement sans qu'il soit nécessaire d'appuyer sur Entrée:

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

Ce sous-programme est écrit en Batch pur, il ne nécessite donc aucun programme supplémentaire et autorise plusieurs opérations d’entrée formatées, telles que lire des chiffres, convertir des lettres en majuscules, etc. Vous pouvez télécharger le sous-programme ReadFormattedLine à partir de Lire une ligne avec format spécifique .


EDIT 2018-08-18 : Nouvelle méthode pour entrer un mot de passe "invisible"

La commande FINDSTR a un bogue étrange qui se produit lorsque cette commande est utilisée pour afficher des caractères en couleur ET que la sortie d'une telle commande est redirigée vers le périphérique CON. Pour plus d'informations sur l'utilisation de la commande FINDSTR pour afficher du texte en couleur, voir cette rubrique .

Lorsque la sortie de cette forme de commande FINDSTR est redirigée vers CON, il se passe quelque chose d'étrange une fois que le texte est affiché dans la couleur souhaitée: tout le texte après sa sortie sous forme de caractères "invisibles", bien qu'une description plus précise soit que le texte est sortie sous forme de texte noir sur fond noir. Le texte d'origine apparaîtra si vous utilisez la commande COLOR pour réinitialiser les couleurs de premier plan et d'arrière-plan de tout l'écran. Cependant, lorsque le texte est "invisible", nous pouvons exécuter une commande SET/P afin que tous les caractères saisis n'apparaissent pas à l'écran.

@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%"
4
Aacini

Si vous avez Python installé, vous pouvez utiliser:

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

le résultat:

Enter the CVS password:
PASS: 123
4
lutecki

créer un fichier de commandes qui appelle celui nécessaire pour les caractères invisibles, puis créer un raccourci pour le fichier de commandes appelé.

clic-droit

propriétés

couleurs

texte == noir

fond == noir

appliquer

d'accord

l'espoir vous aide donc !!!!!!!!

1
cmd

UPDATE:
J'ai ajouté deux nouvelles méthodes qui, au lieu d'utiliser cls pour masquer l'entrée, créent une nouvelle fenêtre contextuelle avec une seule ligne.

Les inconvénients sont qu’une méthode (méthode 2) laisse des fichiers indésirables dans le registre - "Si exécuté sans droits appropriés", et l’autre (méthode 3) ajoute des éléments indésirables au script. Inutile de dire que cela peut facilement être écrit dans n'importe quel fichier tmp et supprimé. J'ai juste essayé de trouver une alternative.

Limitation: Le mot de passe ne peut être que alphanumérique - pas d'autres caractères!

@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.

Mise à jour: J'ai trouvé le message de sachadee est parfait et je viens d'y ajouter mon excentrique "pop-up".

@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
1
Ir Relevant

J'ai utilisé la solution ci-dessus de Blorgbeard, ce qui est excellent à mon avis. Puis je l'ai amélioré comme suit:

  1. Google pour ansicon
  2. Téléchargez le fichier Zip et un exemple de fichier texte.
  3. Installer (cela signifie copier 2 fichiers dans system32)

Utilisez-le comme ceci:

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

Ceci commute la console en gris sur gris pour votre entrée de mot de passe et revient en arrière lorsque vous avez terminé. Le contrôleur doit en fait être un caractère non imprimable, que vous pouvez copier à partir de l'exemple de fichier texte téléchargé (apparaissant comme une flèche vers la gauche dans le Bloc-notes) dans votre fichier de traitement par lots. Vous pouvez utiliser l'exemple de fichier texte pour rechercher les codes de toutes les combinaisons de couleurs.

Si vous n'êtes pas administrateur de la machine, vous pourrez probablement installer les fichiers dans un répertoire non-système. Vous devez ensuite ajouter le répertoire au chemin PATH de votre script avant d'appeler le programme et d'utiliser les séquences d'échappement. Cela pourrait même être le répertoire courant probablement, si vous avez besoin d’un paquet distribuable non-admin contenant seulement quelques fichiers.

1
marcingo

Il s’agit peut-être d’un sujet plus ancien, mais si vous utilisez Windows Vista ou 7, j’ai une solution qui fonctionnera très bien. J'en ai fait une vidéo ici: http://www.youtube.com/watch?v=mk8uAa6PIFM

Pastebin pour le fichier de commandes est ici

0
Nathansswell