Typically, asking the user to supply a file name to a batch script is a messy affair, requiring no misspellings, quotes around paths with spaces, and so forth. Unfortunately, users aren't well-known for accuracy. In situations where input file location is not known until runtime, using a GUI for file selection input reduces the likelihood of user error.
Is there a way to invoke a File... Open style gui file chooser or folder chooser from a Windows batch script?
If the script user has PowerShell or .NET installed, it is possible. See the answer below.
I'm also interested to see what other solutions anyone else can offer.
File Browser
Update 2016.3.20:
Since PowerShell is a native component of pretty much all modern Windows installations nowadays, I'm declaring the C# fallback as no longer necessary. If you still need it for Vista or XP compatibility, I moved it to a new answer. Starting with this edit, I'm rewriting the script as a Batch + PowerShell hybrid and incorporating the ability to perform multi-select. It's profoundly easier to read and to tweak as needed.
<# : chooser.bat
:: launches a File... Open sort of file chooser and outputs choice(s) to the console
:: https://stackoverflow.com/a/15885133/1683264
#echo off
setlocal
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
echo You chose %%~I
)
goto :EOF
: end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
This results in a file chooser dialog.
The result of a selection outputs You chose C:\Users\me\Desktop\tmp.txt to the console. If you want to force single file selection, just change the $f.Multiselect property to $false.
(PowerShell command mercilessly leeched from the Just Tinkering Blog.) See the OpenFileDialog Class documentation for other properties you can set, such as Title and InitialDirectory.
Folder Browser
Update 2015.08.10:
Since there is already a COM method for invoking a folder chooser, it's pretty easy to build a PowerShell one-liner that can open the folder chooser and output the path.
:: fchooser.bat
:: launches a folder chooser and outputs choice to the console
:: https://stackoverflow.com/a/15885133/1683264
#echo off
setlocal
set "psCommand="(new-object -COM 'Shell.Application')^
.BrowseForFolder(0,'Please choose a folder.',0,0).self.path""
for /f "usebackq delims=" %%I in (`powershell %psCommand%`) do set "folder=%%I"
setlocal enabledelayedexpansion
echo You chose !folder!
endlocal
In the BrowseForFolder() method, the fourth argument specifies the root of the hierarchy. See ShellSpecialFolderConstants for a list of valid values.
This results in a folder chooser dialog.
The result of a selection outputs You chose C:\Users\me\Desktop to the console.
See the FolderBrowserDialog class documentation for other properties you can set, such as RootFolder. My original .NET System.Windows.Forms PowerShell and C# solutions can be found in revision 4 of this answer if needed, but this COM method is much easier to read and maintain.
This should work from XP upwards and does'nt require an hibrid file, it just runs mshta with a long command line:
#echo off
set dialog="about:<input type=file id=FILE><script>FILE.click();new ActiveXObject
set dialog=%dialog%('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);
set dialog=%dialog%close();resizeTo(0,0);</script>"
for /f "tokens=* delims=" %%p in ('mshta.exe %dialog%') do set "file=%%p"
echo selected file is : "%file%"
pause
Windows Script Host
File Selection
Windows XP had a mysterious UserAccounts.CommonDialog WSH object which allowed VBScript and JScript to launch the file selection prompt. Apparently, that was deemed a security risk and removed in Vista.
Folder Selection
However, the WSH Shell.Application object BrowseForFolder method will still allow the creation of a folder selection dialog. Here's a hybrid batch + JScript example. Save it with a .bat extension.
#if (#a==#b) #end /*
:: fchooser2.bat
:: batch portion
#echo off
setlocal
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0"') do (
echo You chose %%I
)
goto :EOF
:: JScript portion */
var shl = new ActiveXObject("Shell.Application");
var folder = shl.BrowseForFolder(0, "Please choose a folder.", 0, 0x00);
WSH.Echo(folder ? folder.self.path : '');
In the BrowseForFolder() method, the fourth argument specifies the root of the hierarchy. See ShellSpecialFolderConstants for a list of valid values.
A file / folder selection may be done with pure Batch, as shown below. Of course, the feel and look is not as pleasant as a GUI, but it works very well and in my opinion it is easier to use than the GUI version. The selection method is based on CHOICE command, so it would require to download it in the Windows versions that don't include it and slightly modify its parameters. Of course, the code may be easily modified in order to use SET /P instead of CHOICE, but this change would eliminate the very simple and fast selection method that only requires one keypress to navigate and select.
#echo off
setlocal
rem Select a file or folder browsing a directory tree
rem Antonio Perez Ayala
rem Usage examples of SelectFileOrFolder subroutine:
call :SelectFileOrFolder file=
echo/
echo Selected file from *.* = "%file%"
pause
call :SelectFileOrFolder file=*.bat
echo/
echo Selected Batch file = "%file%"
pause
call :SelectFileOrFolder folder=/F
echo/
echo Selected folder = "%folder%"
pause
goto :EOF
:SelectFileOrFolder resultVar [ "list of wildcards" | /F ]
setlocal EnableDelayedExpansion
rem Process parameters
set "files=*.*"
if "%~2" neq "" (
if /I "%~2" equ "/F" (set "files=") else set "files=%~2"
)
rem Set the number of lines per page, max 34
set "pageSize=30"
set "char=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
rem Load current directory contents
set "name[1]=<DIR> .."
:ProcessThisDir
set "numNames=1"
for /D %%a in (*) do (
set /A numNames+=1
set "name[!numNames!]=<DIR> %%a"
)
for %%a in (%files%) do (
set /A numNames+=1
set "name[!numNames!]= %%a"
)
set /A numPages=(numNames-1)/pageSize+1
rem Show directory contents, one page at a time
set start=1
:ShowPage
set /A page=(start-1)/pageSize+1, end=start+pageSize-1
if %end% gtr %numNames% set end=%numNames%
cls
echo Page %page%/%numPages% of %CD%
echo/
if %start% equ 1 (set base=0) else set "base=1"
set /A lastOpt=pageSize+base, j=base
for /L %%i in (%start%,1,%end%) do (
for %%j in (!j!) do echo !char:~%%j,1! - !name[%%i]!
set /A j+=1
)
echo/
rem Assemble the get option message
if %start% equ 1 (set "mssg=: ") else (set "mssg= (0=Previous page")
if %end% lss %numNames% (
if "%mssg%" equ ": " (set "mssg= (") else set "mssg=%mssg%, "
set "mssg=!mssg!Z=Next page"
)
if "%mssg%" neq ": " set "mssg=%mssg%): "
:GetOption
choice /C "%char%" /N /M "Select desired item%mssg%"
if %errorlevel% equ 1 (
rem "0": Previous page or Parent directory
if %start% gtr 1 (
set /A start-=pageSize
goto ShowPage
) else (
cd ..
goto ProcessThisDir
)
)
if %errorlevel% equ 36 (
rem "Z": Next page, if any
if %end% lss %numNames% (
set /A start+=pageSize
goto ShowPage
) else (
goto GetOption
)
)
if %errorlevel% gtr %lastOpt% goto GetOption
set /A option=start+%errorlevel%-1-base
if %option% gtr %numNames% goto GetOption
if defined files (
if "!name[%option%]:~0,5!" neq "<DIR>" goto endSelect
) else (
choice /C OS /M "Open or Select '!name[%option%]:~7!' folder"
if errorlevel 2 goto endSelect
)
cd "!name[%option%]:~7!"
goto ProcessThisDir
:endSelect
rem Return selected file/folder
for %%a in ("!name[%option%]:~7!") do set "result=%%~Fa"
endlocal & set "%~1=%result%
exit /B
Other solution with direct run PowerShell command in Batch
rem preparation command
set pwshcmd=powershell -noprofile -command "&{[System.Reflection.Assembly]::LoadWithPartialName('System.windows.forms') | Out-Null;$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog; $OpenFileDialog.ShowDialog()|out-null; $OpenFileDialog.FileName}"
rem exec commands powershell and get result in FileName variable
for /f "delims=" %%I in ('%pwshcmd%') do set "FileName=%%I"
echo %FileName%
Batch + PowerShell + C# polyglot solution
This is the same solution as the Batch + PowerShell hybrid, but with the C# fallback stuff re-added for XP and Vista compatibility. Multiple file selection has been added at xNightmare67x's request.
<# : chooser_XP_Vista.bat
:: // launches a File... Open sort of file chooser and outputs choice(s) to the console
:: // https://stackoverflow.com/a/36156326/1683264
#echo off
setlocal enabledelayedexpansion
rem // Does powershell.exe exist within %PATH%?
for %%I in ("powershell.exe") do if "%%~$PATH:I" neq "" (
set chooser=powershell -noprofile "iex (${%~f0} | out-string)"
) else (
rem // If not, compose and link C# application to open file browser dialog
set "chooser=%temp%\chooser.exe"
>"%temp%\c.cs" (
echo using System;
echo using System.Windows.Forms;
echo class dummy {
echo public static void Main^(^) {
echo OpenFileDialog f = new OpenFileDialog^(^);
echo f.InitialDirectory = Environment.CurrentDirectory;
echo f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
echo f.ShowHelp = true;
echo f.Multiselect = true;
echo f.ShowDialog^(^);
echo foreach ^(String filename in f.FileNames^) {
echo Console.WriteLine^(filename^);
echo }
echo }
echo }
)
for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
if not exist "!chooser!" "%%I" /nologo /out:"!chooser!" "%temp%\c.cs" 2>NUL
)
del "%temp%\c.cs"
if not exist "!chooser!" (
echo Error: Please install .NET 2.0 or newer, or install PowerShell.
goto :EOF
)
)
rem // Do something with the chosen file(s)
for /f "delims=" %%I in ('%chooser%') do (
echo You chose %%~I
)
rem // comment this out to keep chooser.exe in %temp% for faster subsequent runs
del "%temp%\chooser.exe" >NUL 2>NUL
goto :EOF
:: // end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
For a folder chooser for XP or Vista, use either the WSH solution or npocmaka's HTA solution.
Two more ways.
1.Using a hybrid .bat/hta (must be saved as a bat) script .It can use vbscript or javascript but the example is with javascrtipt.Does not create temp files.Selecting folder is not so easy and will require an external javascript libraries , but selecting file is easy
<!-- : starting html comment
:: FileSelector.bat
#echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
set "file=%%~fp"
)
echo/
if not "%file%" == "" (
echo selected file is : %file%
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
<script language='javascript'>
function pipeFile() {
var file=document.getElementById('file').value;
var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
close(fso.Write(file));
}
</script>
<input type='file' name='file' size='30'>
</input><hr><button onclick='pipeFile()'>Submit</button>
</body>
1.1 - without submit form proposed by rojo (see comments):
<!-- : starting html comment
:: FileSelector.bat
#echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
set "file=%%~fp"
)
echo/
if not "%file%" == "" (
echo selected file is : "%file%"
)
echo/
exit /b
-->
<Title>== FILE SELECTOR==</Title>
<body>
<script language='javascript'>
function pipeFile() {
var file=document.getElementById('file').value;
var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
close(fso.Write(file));
}
</script>
<input id='file' type='file' name='file' size='30' onchange='pipeFile()' >
</input>
<hr>
<button onclick='pipeFile()'>Submit</button>
<script>document.getElementById('file').click();</script>
</body>
2.As you already using powershell/net you can create selfcompiled jscript.net hybrid.It will not require temp cs file for compilation and will directly use the built-in jscrript.net compiler.There's no need of powershell too and the code is far more readable:
#if (#X)==(#Y) #end /* JScript comment
#echo off
:: FolderSelectorJS.bat
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 "folder=%%p"
)
if not "%folder%" == "" (
echo selected folder is %folder%
)
endlocal & exit /b %errorlevel%
*/
import System;
import System.Windows.Forms;
var f=new FolderBrowserDialog();
f.SelectedPath=System.Environment.CurrentDirectory;
f.Description="Please choose a folder.";
f.ShowNewFolderButton=true;
if( f.ShowDialog() == DialogResult.OK ){
Console.Write(f.SelectedPath);
}
I will leave an 'echo' even to verify that multiple choice works in this code
echo off
set cmd=Add-Type -AssemblyName System.Windows.Forms;$f=new-object Windows.Forms.OpenFileDialog;$f.InitialDirectory= [environment]::GetFolderPath('Desktop');$f.Filter='Text Files(*.txt)^|*.txt^|All Files(*.*)^|*.*';$f.Multiselect=$true;[void]$f.ShowDialog();if($f.Multiselect) {$f.FileNames}else{$f.FileName}
set pwshcmd=powershell -noprofile -command "&{%cmd%}"
for /f "tokens=* delims=" %%I in ('%pwshcmd%') do call :sum "%%I" ret
echo =========
echo --%ret%--
pause
exit /B
:sum [mud] [ret]
echo "%~1"
set FileName=%FileName% "%~1"
set ret=%FileName%
exit /B
I has been wrote my own portable solution:
https://github.com/andry81/contools/tree/HEAD/Utilities/src/_gui/wxFileDialog/
You can download executable from here:
https://github.com/andry81/contools/tree/HEAD/Utilities/bin/contools/wxFileDialog.exe
The utility has dependency on wxWidgets 3.1.x, so you can actually build it for other operating systems.
I searched for any way to query a process hash.
assuming I was able to retrive the ExecutablePath using Win32_Process,
I would like to query the file's hash.
I'm trying to avoid using powershell but to achieve the same functiallity of "Get-FileHash".
Thank You!
edit:
I have tried to use win32_filespecification that supplied md5checksum, the problem was i could not find the relevant files (such as notepad.exe).
Here is a batch file to test :
#echo off
Title Get Notepad Hash
Set "App_Path=%windir%\system32\notepad.exe"
echo "%App_Path%"
#for /f "tokens=2 skip=3 delims= " %%a in ('Powershell Get-FileHash "%App_Path%"') do echo SHA256=%%a
Pause & Exit
EDIT :
Get Process File Hash using WMIC and Certutil in command line
You can give a try for the second batch file :
#echo off
cls & color 9E & Mode 95,5
Title Get Process File Hash using WMIC and Certutil in command line
Set "TmpFile=%~dpn0_Tmp.txt"
Set "LogPathExe=%~dpn0_PathExe.txt"
Set "Hashes=%~dpn0_Hashes.txt"
echo(
echo( ===========================================================
echo( Please wait a while ... Working is in progress....
echo( ===========================================================
Setlocal EnableDelayedExpansion
> "!TmpFile!" (
#for /f "delims=" %%a in ('wmic process get ExecutablePath /format:list') do (
#For /F "tokens=2 delims==" %%b in ("%%a") do (
set "Exe=%%b"
If not defined Exe Set !Exe!
echo "!Exe!"
)
)
)
Call :RemoveDuplicateEntry "!TmpFile!" "!LogPathExe!"
Del "!TmpFile!"
> "!Hashes!" (
#for /f "delims=" %%a in ('Type "!LogPathExe!"') do (
#for /f "skip=1 delims=" %%H in ('CertUtil -hashfile "%%~a" SHA256 ^| findstr /i /v "CertUtil"') do set "H=%%H"
echo %%a=!H: =!
)
)
)
If Exist "!Hashes!" Start "" "!Hashes!" & Exit
::----------------------------------------------------
:RemoveDuplicateEntry <InputFile> <OutPutFile>
Powershell ^
$Contents=Get-Content '%1'; ^
$LowerContents=$Contents.ToLower(^); ^
$LowerContents ^| select -unique ^| Out-File '%2'
Exit /b
::----------------------------------------------------
The third batch script to check hashes on virustotal :
#echo off
cls & color 9E & Mode 95,5
Title Get Process File Hash using WMIC and Certutil in command line
Set "TmpFile=%~dpn0_Tmp.txt"
Set "LogPathExe=%~dpn0_PathExe.txt"
Set "Hashes=%~dpn0_Hashes.txt"
Set "Hash2Check_VirusTotal=%~dpn0_Hash2Check_VirusTotal.txt"
If Exist "%Hash2Check_VirusTotal%" Del "%Hash2Check_VirusTotal%"
echo(
echo( ===========================================================
echo( Please wait a while ... Working is in progress....
echo( ===========================================================
Setlocal EnableDelayedExpansion
> "!TmpFile!" (
#for /f "delims=" %%a in ('wmic process get ExecutablePath /format:list') do (
#For /F "tokens=2 delims==" %%b in ("%%a") do (
set "ExecutablePath=%%b"
If not defined ExecutablePath Set !ExecutablePath!
echo "!ExecutablePath!"
)
)
)
Call :RemoveDuplicateEntry "!TmpFile!" "!LogPathExe!"
Del "!TmpFile!"
> "!Hashes!" (
#for /f "delims=" %%a in ('Type "!LogPathExe!"') do (
#for /f "skip=1 delims=" %%H in ('CertUtil -hashfile "%%~a" SHA256 ^| findstr /i /v "CertUtil"') do set "H=%%H"
echo %%a=!H: =!
>> "!Hash2Check_VirusTotal!" echo https://www.virustotal.com/old-browsers/file/!H: =!
)
)
)
cls
Echo(
Echo( Did you want to check the executable on Virustotal ? Just Type "Y" Or any key to Quit !
Set /p "Check="
If /I [!check!] EQU [Y] (
#for /f "delims=" %%a in ('Type "!Hash2Check_VirusTotal!"') do ( Start "Chek SHA256 on VIRUSTOTAL" %%a & Timeout /T 10 /nobreak>nul)
) else (
If Exist "!Hashes!" Start "" "!Hashes!" & Exit
)
Exit
::----------------------------------------------------
:RemoveDuplicateEntry <InputFile> <OutPutFile>
Powershell ^
$Contents=Get-Content '%1'; ^
$LowerContents=$Contents.ToLower(^); ^
$LowerContents ^| select -unique ^| Out-File '%2'
Exit /b
::----------------------------------------------------
Using Windows command line (not powershell), I want to hash all files within the directory and then remove files that match a particular hash set contained within a text file.
I've considered using md5deep, but I'm unsure if the output of matched files can then be redirected into a delete command.
Any help gratefully received, thank you!
To add some detail; the files are in a directory called 'images'
md5deep.exe -r -b -x irrelevant_hashes.txt c:\images
This gives me a list of the files that I need to keep. Is it possible to redirect the output from MD5deep to move the 'good' files to another directory?
For a single md5 key in cmd line it is as easy as:
(Here using the 64bit variant).
set "KillMD5=00112233445566778899aabbccddeeff"
for /f "tokens=1*" %A in ('md5deep64.exe *.* 2^>mul') do #if %A==%KillMD5% #Echo del "%B"
For testing the del command is only echoed.
In a batch file double the % percent signs %%A/%%B
This use pure batch file, take use of CertUtil from windows, so no 3rd software need.
You only need provide the value for 2 variables:
set _nOp=irrelevant_hashes.txt :: file text with md5 data for files to delete
set "_path_gen=c:\images" :: path to files that will be delete.
In additional, put the txt file with md5 (in this code case irrelevant_hashes.txt) in the same folder of the files that you want to delete.
For generate a new md5 from files, and usin certUtil on command line:
type nul >"%temp%\MD5_to_del.txt" & cd /d "c:\images" & for /f "tokens=* delims= " %i in ('^<nul dir /o-d /on /b "c:\images\*.*"') do for /f "tokens=* delims= " %M in ('certutil -hashfile "%i" md5 ^| find /v ":"') do echo/%M>>"%temp%\MD5_to_del.txt"
For generate a new md5 from files, and using certUtil on a file.bat:
type nul >"%temp%\MD5_to_del.txt" & cd /d "c:\images" & for /f "tokens=* delims= " %%i in ('^<nul dir /o-d /on /b "c:\images\*.*"') do for /f "tokens=* delims= " %%M in ('certutil -hashfile "%%i" md5 ^| find /v ":"') do echo/%%M>>"%temp%\MD5_to_del.txt"
#echo off & setlocal EnableExtensions EnableDelayedExpansion
cls && mode con cols=120 lines=7 & cd /d "%~dp0"
set "'=^|"
set "_spc= "
set /a _cnt_left= 1 - 1
set /a _cnt_treated= 1 - 1
set /a _cnt_deleted= 1 - 1
set /a _cnt_keeped_= 1 - 1
set _type_hash=md5
set _show=0000000
set "_path_gen=c:\images"
cd /d !_path_gen! || set "_erro=!_path_gen! not exist?"&& goto :_error_:
set _n_deleted=%temp%\md5_not_deleted_.txt
set _y_deleted=%temp%\md5_was_deleted_.txt
(
if exist "!_n_deleted!" del /q /f "!_n_deleted!"
if exist "!_y_deleted!" del /q /f "!_y_deleted!"
) 2>nul >nul
if exist ".\irrelevant_hashes.txt" (
set _nOp=irrelevant_hashes.txt
) else (
set "_error= File irrelevant_hashes.txt not found"
goto :_error_:
)
set _hash_data=%temp%\hash_db\date_db.txt
if exist "!_hash_data!" (
del /q /f "!_hash_data!"
copy /y "!_nOp!" "!_hash_data!" 2>nul >nul || set _error=Copy !_nOp! to !_hash_data!
) else (
dir /ad "%temp%\hash_db\" 2>nul >nul | findstr /c:".." || mkdir "%temp%\hash_db"
copy /v "!_nOp!" "!_hash_data!" 2>nul >nul || set _error=Copy !_nOp! to !_hash_data!
)
for /f "delims= " %%T in ('forFiles /p "." /m "%~nx0" /c "cmd /c echo(0x09"') do set "_tab=%%T"
call set "_tab=%_tab:~0,1%"
for /f "tokens=* delims=^ " %%i in ('^<nul dir /o-d /on /b "!_path_gen!\*.*" 2^> nul ^| find "" /v /c ') do set _cnt_file=%%i
for /f "tokens=* delims= " %%f in ('dir /o-d /on /b "*.*" ^| findstr /i /v "!_nOp! %0" ') do (
for %%S in (cnt_treated cnt_deleted cnt_keeped_ cnt_left) do set _show_%%S=!_show!!_%%S!
set _file=%%~nxf
set "_file_hash=%%~dpnxf"
set /a _cnt_treated=!_cnt_treated! + 1
call :_get_hash_:
title Total files: !_show_cnt_treated:~-5! ^| Delete: !_show_cnt_deleted:~-5! ^| Keeped: !_show_cnt_keeped_:~-5! ^| File left: !_show_cnt_left:~-5!
)
(
if exist "!_n_deleted!" copy /y "!_n_deleted!" .
if exist "!_y_deleted!" del /y "!_y_deleted!" .
) 2>nul >nul
echo/ Total file treated: !_show_cnt_treated:~-5!
echo/ Total file deleted: !_show_cnt_deleted:~-5!
echo/ Total file keeped: !_show_cnt_keeped_:~-5!
goto :_end_of_file_:
:_get_hash_:
for /f "tokens=* delims= " %%i in ('certutil -hashfile "!_file_hash!" !_type_hash! ^| find /v ":"') do (
set "_hash=%%i"
call set "_hash=!_hash: =!"
call set _hash=!_hash!
for /f "tokens=* delims=" %%I in ('echo/%_tab%') do call set _file_hash=!_hash:%%I=!
call set _hash=!_hash!
for /f "tokens=* delims= " %%e in ('type "!_hash_data!" ^| findstr /i /l /c:"!_hash!"') do set _hash_db=%%e
if "!_hash_db!" equ "" set "_hash_db=- So, no found^!! not "
echo/ & echo/ File hash md5 from: "!_file!" & echo/
echo/!_spc!Hash !_type_hash!: !_hash!
echo/ Data hash md5 ^(db^): !_hash_db! equals?
call :_delete_md5_:
call set /a _cnt_left=!_cnt_file! - 1 - !_cnt_keeped_!
)
timeout /t 10 2>nul >nul
)
)
for %%C in (file_hash hash strn_hash strn_hash hash_nul hash_db) do set _%%C=
exit /b
:_delete_md5_:
if /i "!_hash_db!" equ "!_hash!" del /q /f "!_path_gen!\!_file!"
if not exist "!_path_gen!\!_file!" (
echo/!_file! !_strn_hash!>>"!_y_deleted!"
echo/!_spc!!_spc:~-10!!_hash! "!_file!" file was deleted^^!
call set /a _cnt_file=!_cnt_file! - 1
call set /a _cnt_deleted=!_cnt_deleted! + 1
exit /b
) else (
echo/!_file! !_strn_hash!>>"!_n_deleted!"
echo/!_spc!!_spc:~-10!!_hash! "!_file!" file not was deleted^^!
call set /a _cnt_keeped_=!_cnt_keeped_! + 1
exit /b
)
:_error_:
echo/ & echo/ & echo/ !_error!
goto :_end_of_file_:
:_end_of_file_:
This question already has answers here:
Can I mask an input text in a bat file?
(19 answers)
Closed 6 years ago.
I have a requirement like whenever we execute a test.bat file then it should ask enter password and entered password should be hidden with *****.
Is there any simplest way in batch programming for the above requirement?
I have written the below script using PowerShell is it fine/recommended to use PowerShell for this or any other simplest way is available?
#ECHO OFF
setlocal
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=" %%G in (`%psCommand%`) do set password=%%G
echo "%password%"
endlocal
Also suggest how to terminate the batch file as Ctrl+C is not working?
Give a try with this little example :
#echo off
Title %~n0 by Hackoo 2016
Mode 50,5 & Color 0E
:CreatePassword
cls & Color 0E
setlocal DisableDelayedExpansion
Call :InputPassword "Please choose your password" pass1
Call :InputPassword "Please confirm your password" pass2
setlocal EnableDelayedExpansion
If !pass1!==!pass2! ( Goto:Good ) Else ( Goto:Bad )
::***********************************
:InputPassword
Cls
echo.
echo.
set "psCommand=powershell -Command "$pword = read-host '%1' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set %2=%%p
Goto :eof
::***********************************
:Good
Color 0B
Cls
echo.
echo Good password
::TimeOut /T 2 /NoBreak>nul
echo Your password stored as : "!Pass2!" without quotes
pause>nul
Goto :Eof
::***********************************
:Bad
Color 0C
Cls
echo.
echo Wrong password try again
::TimeOut /T 2 /NoBreak>nul
echo Press any key to retry again
pause>nul
Goto :CreatePassword
::***********************************
And you can also give a try for this complete example Folder Loker.bat
Edit on 31/03/2016 # 14:43
Another way in pur batch based on replace command
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
Set /P "=Enter a Password:" < Nul
Call :PasswordInput
Echo(Your input was:!Line!
pause
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
And this is another version improved by aGerman
#echo off & setlocal
Title %~n0
Mode 50,5 & Color 9E
Set /P "Pass1=Please choose your Password:" < Nul
call :HInput Pass1
echo Input length is %errorlevel%
setlocal EnableDelayedExpansion
echo Your password is !Pass1!
pause
cls
Set /P "Pass2=Please confirm your Password:" < Nul
call :HInput Pass2
echo Input length is %errorlevel%
echo Your password is !Pass2!
pause
cls
If !Pass1!==!Pass2! (echo the two passwords are the same
) else (echo the two passwords does not match)
pause
goto :eof
:HInput [ByRef_VarName]
:: inspired by Carlos
if "%__HI__%" neq "__HI__" (
setlocal DisableDelayedExpansion EnableExtensions
set "CR=" &set "S=" &set "N=0" &set "__HI__=__HI__"
for /f "skip=1" %%i in ('echo(^|replace ? . /u /w') do if not defined CR set "CR=%%i"
for /f %%i in ('"prompt $H &for %%b in (1) do rem"') do set "BS=%%i"
)
set "C="
for /f skip^=1^ delims^=^ eol^= %%i in ('replace ? . /u /w') do if not defined C set "C=%%i"
setlocal EnableDelayedExpansion EnableExtensions
if "!CR!"=="!C!" (
echo(
if "%~1"=="" (
echo(!S!
endlocal &endlocal &exit /b %N%
) else (
if defined S (
for /f delims^=^ eol^= %%i in ("!S!") do endlocal &endlocal &set "%~1=%%i" &exit /b %N%
) else endlocal &endlocal &set "%~1=" &exit /b 0
)
)
if "!BS!"=="!C!" (
set "C="
if defined S set /a "N -= 1" &set "S=!S:~,-1!" &<nul set /p "=%BS% %BS%"
) else set /a "N += 1" &<nul set /p "=*"
if not defined S (
endlocal &set "N=%N%" &set "S=%C%"
) else for /f delims^=^ eol^= %%i in ("!S!") do endlocal &set "N=%N%" &set "S=%%i%C%"
goto HInput
Hi for everyone in stackoverflow !
I'm looking for a workaround to how delete this kind of file using a reserved name such :
(nul, aux, com1, prn, etc...)
So, i get as output error :
The syntax of the file name, directory or volume incorrect.
#echo off
echo hello world>\\?\"%temp%\nul:nul"
pause
more<"%temp%\nul:nul"
pause
set /p MyVar=<"\\?\%temp%\nul:nul"
echo %MyVar%
Pause
Del "\\?\%temp%\nul:nul" /F
pause
I'm using this trick to store the password shown like in this code below
so, i can set the password into this file and also, read from it, but i can't delete it.
#echo off
Title %~n0 with colors by Hackoo
Mode 50,5 & Color 0E
Setlocal EnableDelayedExpansion
:CreatePassword
Call :InputPassword "Please choose your password" pass1
Call :InputPassword "Please confirm your password" pass2
If !pass1!==!pass2! ( Goto:Good ) Else ( Goto:Bad )
::***********************************
:InputPassword
Cls
echo.
echo.
set "psCommand=powershell -Command "$pword = read-host '%1' -AsSecureString ; ^
$BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
[System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set %2=%%p
Goto :eof
::***********************************
:Good
Cls
echo.
echo.
Call :Color 0B " Good password " 1
TimeOut /T 2 /NoBreak>nul
Call :Write_Info
Call :Collect_Info
echo Your password stored as : "!SavedPass!" without quotes
pause
Goto :Eof
::***********************************
:Bad
Cls
echo.
echo.
Call :Color 0C " Wrong password try again " 1
TimeOut /T 2 /NoBreak>nul
Goto :CreatePassword
::***********************************
:Color
for /F "delims=." %%a in ('"prompt $H. & for %%b in (1) do rem"') do set "BS=%%a"
set nL=%3
if not defined nL echo Requires third argument & Pause > nul & goto :Eof
if %3 == 0 (
<nul set /p ".=%BS%">%2 & Findstr /V /A:%1 /R "^$" %2 nul & Del %2 2>&1
goto :Eof
) else if %3 == 1 (
echo %BS%>%2 & Findstr /V /A:%1 /R "^$" %2 nul & Del %2 2>&1
goto :Eof
)
::***********************************
:Write_Info
(echo !Pass2!)>\\?\"%temp%\nul:nul"
Call :Color 0A " Your password is set sucessfuly" 1
::***********************************
:Collect_Info
(set /P SavedPass=)<"\\?\%temp%\nul:nul"
goto :eof
::***********************************
This worked for me:
del "\\.\%temp%\nul"
As Microsoft says in
https://support.microsoft.com/en-us/kb/120716,
you need to use a syntax which bypasses the check for reserved names.