I'm trying to write two batch files that will allow me to switch the Power Scheme (Control Panel -> Power Options -> Power Schemes Tab) from Home/Office Desk to Portable/Laptop and back. My operating system is Windows XP SP3.
My reason for doing this is because I want to disable SpeedStep when I'm playing games on my laptop (i.e. put it on the Home/Office Desk scheme) and enable SpeedStep otherwise (back to Portable/Laptop). Windows XP turns turns off dynamic switching in Home/Office Desk mode. I'd like to be able to do this programatically to save myself some time everytime I want to play a game.
Any thoughts on how to modify the power settings using a simple batch file? Python and Ruby scripting is also an option but isn't preferred.
C:>%windir%\system32\powercfg.exe /?
/SETACTIVE, /S Makes the power scheme with the specified name active.
Examples:
POWERCFG /SETACTIVE scheme
#echo off
setlocal EnableDelayedExpansion
echo Available power schemes:
echo/
set i=0
set "options="
for /F "tokens=2,3 delims=:()" %%a in ('powercfg /L') do if "%%b" neq "" (
set /A i+=1
set "options=!options!!i!"
echo !i!. %%b
set "scheme[!i!]=%%a"
)
echo/
choice /C %options% /N /M "Select desired scheme: "
powercfg /S !scheme[%errorlevel%]!
echo/
echo Power scheme set
Perhaps you need to adjust the "tokens=2,3 delims=:()" FOR options; this code was written for Windows 8.1 Spanish version.
Related
Working on a Caffinate Alternative for Windows and was wondering if there was a way I could grab just the GUID of the current used powerplan without the rest of the output heres a example of what I mean.
What I am getting... when using powercfg /list
Existing Power Schemes (* Active)
-----------------------------------
Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced) *
What I want...
381b4222-f694-41f0-9685-ff5bb260df2e
This is so I can refrence it and reload it in once caffinate is finished.
#ECHO OFF
SETLOCAL
FOR /f "tokens=1-4" %%g IN ('powercfg /list^|find "*" ') DO IF "%%g%%h%%i"=="PowerSchemeGUID:" SET "guid=%%j"
ECHO guid=%guid%
GOTO :EOF
If you want other guids from the list, simply substitute Balanced High performance or Power saver (or whatever else you may need) for *
With Windows 10 is it possible to setup up known networks and be able to connect to them without all the mouse movement and click?
Using Windows batch files, you can set it up to connect to networks you already know (Network1 or Network2, below) without ever touching the mouse.
#echo off
setlocal EnableDelayedExpansion
for %%i in ("Network1"
"Network2") do (
netsh wlan show networks mode=ssid | findstr /C:%%i
if !ERRORLEVEL! EQU 0 (
echo "Found %%~i - connecting..."
netsh wlan connect name=%%i
exit /b
) else (
echo "Did not find %%~i"
)
)
#echo on
Save the above to .bat and run it from cmd.exe or a program like Listary.
Some comments about the code:
If more than one of your listed networks are available, it will connect to whichever is first in the for loop list. You could also put the list in a file and change for %%i to for /F %%i
EnableDelayedExpansion and "!" around ERRORLEVEL
are needed to keep the variable ERRORLEVEL from being assigned
whatever it was at the beginning of the script. Since I don't
normally program Windows batch files, this is 2 hours of my life
gone that you won't have to deal with.
All the echoing is for debugging; the echo off at the top squelches it.
%% needed for variables in Windows batch files. The variable is referenced with % at the command line.
%%~i strips the quotation marks around the string when outputting to stdout.
I have a Portable VirtualBox set up on one of my hard drives (Portable Virtual Box). And I have another VirtualBox installed in my system (this one is NOT portable, but classic installation in C:\Program Files)
I'm trying to use a BATCH Script to retrieve the location of the running VirtualBox:
#echo off
cls
setlocal enabledelayedexpansion
ECHO Please make sure you have VirtualBox running, so the script
ECHO will be able to detect VirtualBox.exe process running
rem because of a bug in wmic, I have to get the Input Locale first.
rem I could have had it hardcoded, but I think this is better (more flexible)
for /f "tokens=2 delims=:,;" %%s in ('systeminfo ^| find /i "Input Locale:"') DO (
SET locale=%%~ns
set locale=!locale: =!
)
rem this is the actual search for the executable location
FOR /f "tokens=2 delims=," %%I IN ('wmic process where "name='virtualbox.exe'" get ExecutablePath^,Handle /Format:"%WINDIR%/System32/wbem/!locale!/csv" ^| FIND /i "virtualbox.exe"') DO SET "exepath=%%~I"
ECHO Detected Path: !exepath!
endlocal
But I always get
"C:\Program Files\Oracle\VirtualBox\VirtualBox.exe".
I tried from Task Manager (right click > Open File Location) and it happens the same, no matter which of the VirtualBox instances is running.
Uninstalling the version in my "C:\Program Files" enabled proper detection of the portable one.
Is it any way (using BATCH) to correctly detect running process executable location (VirtualBox.exe, in my case), when the situation is similar with the one described above (running a portable version of an already installed program)?
I'm writing a Windows batch file and want to copy something to the desktop. I think I can use this:
%UserProfile%\Desktop\
However, I'm thinking, that's probably only going to work on an English OS. Is there a way I can do this in a batch file that will work on any internationalized version?
UPDATE
I tried the following batch file:
REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop
FOR /F "usebackq tokens=3 skip=4" %%i in (`REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop`) DO SET DESKTOPDIR=%%i
FOR /F "usebackq delims=" %%i in (`ECHO %DESKTOPDIR%`) DO SET DESKTOPDIR=%%i
ECHO %DESKTOPDIR%
And got this output:
S:\>REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
Desktop REG_EXPAND_SZ %USERPROFILE%\Desktop
S:\>FOR /F "usebackq tokens=3 skip=4" %i in (`REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folder
s" /v Desktop`) DO SET DESKTOPDIR=%i
S:\>FOR /F "usebackq delims=" %i in (`ECHO ECHO is on.`) DO SET DESKTOPDIR=%i
S:\>SET DESKTOPDIR=ECHO is on.
S:\>ECHO ECHO is on.
ECHO is on.
To be safe, you should use the proper APIs in Powershell (or VBScript)
Using PowerShell:
[Environment]::GetFolderPath("Desktop")
Copy something using Powershell:
Copy-Item $home\*.txt ([Environment]::GetFolderPath("Desktop"))
Here is a VBScript-example to get the desktop path:
dim WSHShell, desktop, pathstring, objFSO
set objFSO=CreateObject("Scripting.FileSystemObject")
Set WSHshell = CreateObject("WScript.Shell")
desktop = WSHShell.SpecialFolders("Desktop")
pathstring = objFSO.GetAbsolutePathName(desktop)
WScript.Echo pathstring
I found that the best solution is to use a vbscript together with the batch file.
Here is the batch file:
#ECHO OFF
FOR /F "usebackq delims=" %%i in (`cscript findDesktop.vbs`) DO SET DESKTOPDIR=%%i
ECHO %DESKTOPDIR%
Here is findDesktop.vbs file:
set WshShell = WScript.CreateObject("WScript.Shell")
strDesktop = WshShell.SpecialFolders("Desktop")
wscript.echo(strDesktop)
There may be other solutions but I personally find this one less hackish.
I tested this on an English PC and also a French PC - it seems to work (Windows XP).
EDIT: Use the accepted answer, this will not work if the default location isn't being used, for example: The user moved the desktop to another drive like D:\Desktop
At least on Windows XP, Vista and 7 you can use the "%UserProfile%\Desktop" safely.
Windows XP en-US it will expand to "C:\Documents and Settings\YourName\Desktop"
Windows XP pt-BR it will expand to "C:\Documents and Settings\YourName\Desktop"
Windows 7 en-US it will expand to "C:\Users\YourName\Desktop"
Windows 7 pt-BR it will expand to "C:\Usuarios\YourName\Desktop"
On XP you can't use this to others folders exept for Desktop
My documents turning to Meus Documentos and Local Settings to Configuracoes locais Personaly I thinks this is a bad thing when projecting a OS.
KB's answer to use [Environment]::GetFolderPath("Desktop") is obviously the official Windows API for doing this.
However, if you're working interactively at the prompt, or just want something that works on your machine, the tilda (~) character refers to the current user's home folder. So ~/desktop is the user's desktop folder.
Not only would that not work for an International version of Windows, it would fail if the user had edited the Registry to make their Desktop folder reside somewhere else. You can query the Registry for the file location using the REG command:
REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop
To get this into a variable use something like this:
FOR /F "usebackq tokens=3 skip=4" %%i in (`REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop`) DO SET DESKTOPDIR=%%i
FOR /F "usebackq delims=" %%i in (`ECHO %DESKTOPDIR%`) DO SET DESKTOPDIR=%%i
ECHO %DESKTOPDIR%
you could also open a DOS command prompt and execute the set command.
This will give you an idea what environment variables are available on your system.
E.g. - since you where specifically asking for a non-english Windows - heres is an example of my own German Edition (Window7-64bit) :
set > env.txt
type env.txt
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\SOF\AppData\Roaming
CommonProgramFiles=C:\Program Files\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
CommonProgramW6432=C:\Program Files\Common Files
COMPUTERNAME=VMSOF
ComSpec=C:\Windows\system32\cmd.exe
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=\Users\SOF
LOCALAPPDATA=C:\Users\SOF\AppData\Local
LOGONSERVER=\\VMSOF
NUMBER_OF_PROCESSORS=2
OS=Windows_NT
Path=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\TortoiseSVN\bin;C:\Program Files (x86)\CMake 2.8\bin;C:\Program Files (x86)\emacs-22.3\bin;C:\Program Files (x86)\GnuWin32\bin;
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=AMD64 Family 15 Model 67 Stepping 3, AuthenticAMD
PROCESSOR_LEVEL=15
PROCESSOR_REVISION=4303
ProgramData=C:\ProgramData
ProgramFiles=C:\Program Files
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
PROMPT=$P$G
PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
PUBLIC=C:\Users\Public
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\Windows
TEMP=C:\Users\SOF\AppData\Local\Temp
TMP=C:\Users\SOF\AppData\Local\Temp
USERDOMAIN=VMSOF
USERNAME=SOF
USERPROFILE=C:\Users\SOF
VBOX_INSTALL_PATH=C:\Program Files\Sun\VirtualBox\
VS90COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\
windir=C:\Windows
in windows 7 this returns the desktop path:
FOR /F "usebackq tokens=3 " %%i in (`REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop`) DO SET DESKTOPDIR=%%i
FOR /F "usebackq delims=" %%i in (`ECHO %DESKTOPDIR%`) DO SET DESKTOPDIR=%%i
ECHO %DESKTOPDIR%
If you wish to use the
[Environment]::GetFolderPath("Desktop")
from within a cmd.exe, you may do so (thanks to MS User Marian Pascalau on this thread)
set dkey=Desktop
set dump=powershell.exe -NoLogo -NonInteractive "Write-Host $([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::%dkey%))"
for /F %%i in ('%dump%') do set dir=%%i
echo Desktop directory is %dir%
This is not a solution but I hope it helps: This comes close except that when the KEY = %userprofile%\desktop the copy fails even though zdesktop=%userprofile%\desktop. I think because the embedded %userprofile% is not getting translated.
REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop>z.out
for /f "tokens=3 skip=4" %%t in (z.out) do set zdesktop=%%t
copy myicon %zdesktop%
set zdesktop=
del z.out
So it sucessfully parses out the REG key but if the key contains an embedded %var% it doesn't get translated during the copy command.
I had a similar problem (and VBScript or PowerShell was not an option) and the code I found in this article did not work for me. I had problems with OS versions and language versions. After some experiments I've come to this solution:
for /f "usebackq tokens=2,3*" %%A in (`REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Desktop"`) do if %%A==REG_EXPAND_SZ call :reparse set desktopdir=%%B
echo %desktopdir%
goto :EOF
:reparse
%*
goto :EOF
This code works for me in English and Polish versions of Windows 7 and Windows XP.
The :reparse subroutine allows for delayed expansion of environment variables.
While I realize this is a bit of an older post, I thought this might help people in a similar situation. I made a quick one line VBScript to pull info for whatever special folder you would like (no error checking though) and it works like this:
Create a file "GetShellFolder.vbs" with the following line:
WScript.Echo WScript.CreateObject("WScript.Shell").SpecialFolders(WScript.Arguments(0))
I always make sure to copy cscript.exe (32-bit version) to the same folder as the batch file I am running this from, I will assume you are doing the same (I have had situations where users have somehow removed C:\Windows\system32 from their path, or managed to get rid of cscript.exe, or it's infected or otherwise doesn't work).
Now copy the file to be copied to the same folder and create a batch file in there with the following lines:
for /f "delims=" %%i in ('^""%~dp0cscript.exe" "%~dp0GetShellFolder.vbs" "Desktop" //nologo^"') DO SET SHELLDIR=%%i
copy /y "%~dp0<file_to_copy>" "%SHELLDIR%\<file_to_copy>"
In the above code you can replace "Desktop" with any valid special folder (Favorites, StartMenu, etc. - the full official list is at https://msdn.microsoft.com/en-us/library/0ea7b5xe%28v=vs.84%29.aspx) and of course <file_to_copy> with the actual file you want placed there. This saves you from trying to access the registry (which you can't do as a limited user anyway) and should be simple enough to adapt to multiple applications.
Oh and for those that don't know the "%~dp0" is just the directory from which the script is being called. It works for UNC paths as well which makes the batch file using it extremely portable. That specifically ends in a trailing "\" though so it can look a little odd at first glance.
#Dave Webb's answer is probably the way to go. The only other thing I can think of are the CSIDLs:
CSIDL_DESKTOPDIRECTORY
The file system directory used to
physically store file objects on the
desktop (which should not be confused
with the desktop folder itself). A
typical path is C:\Documents and
Settings\username\Desktop.
I have no idea how to get hold of those from the command line, though.
Multilingual Version, tested on Japanese OS Batch File
set getdesk=REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop
FOR /f "delims=(=" %%G IN ('%getdesk% ^|find "_SZ"') DO set desktop=%%G
set desktop1=%desktop:*USERPROFILE%\=%
cd "%userprofile%\%desktop1%"
set getdesk=
set desktop1=
set desktop=
This should work no matter what language version of Windows it is and no matter where the folder is located. It also doesn't matter whether there are any spaces in the folder path.
FOR /F "tokens=2*" %%A IN ('REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop^|FIND/I "desktop"') DO SET Desktop=%%B
ECHO %Desktop%
In case of Windows 2000 (and probably NT 4.0) you need to copy reg.exe to the %windir% folder manually since it is not available there by default.
I use this code to get the User desktop and Public desktop paths from the registry, tested on Windows XP SP2 pt-PT and Windows 10 b14393 en-US, so it probably works in Vista/7/8 and other languages.
:: get user desktop and public desktop paths
for /f "tokens=* delims= " %%a in ('reg query "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop ^|find /i "REG_"') do set "batch_userdesktop=%%a"
for /f "tokens=* delims= " %%a in ('reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Common Desktop" ^|find /i "REG_"') do set "batch_publicdesktop=%%a"
:: remove everything up to and including "_SZ"
set "batch_userdesktop=%batch_userdesktop:*_sz=%"
set "batch_publicdesktop=%batch_publicdesktop:*_sz=%%
:: remove leading spaces and TABs
:loop
if "%batch_userdesktop:~0,1%"==" " set "batch_userdesktop=%batch_userdesktop:~1%" & goto loop
if "%batch_publicdesktop:~0,1%"==" " set "batch_publicdesktop=%batch_publicdesktop:~1%" & goto loop
if "%batch_userdesktop:~0,1%"==" " set "batch_userdesktop=%batch_userdesktop:~1%" & goto loop
if "%batch_publicdesktop:~0,1%"==" " set "batch_publicdesktop=%batch_publicdesktop:~1%" & goto loop
The last two lines include a TAB inside the " ", some text editors add spaces when you press TAB, so make sure you have an actual TAB instead of spaces.
I'm not sure the code requires setlocal enabledelayedexpansion, it's part of my SETVARS.CMD which I call from other batches to set common variables like cpu architecture, account language, windows version and service pack, path to user/public desktop, etc.
I know this is kind of an old topic, but I would use the Powershell variable
$env:UserProfile
To use it to get to the desktop, it would be:
cd $env:UserProfile\desktop
This works both locally and remotely on windows 7. Hope this is useful as I ran across a situation where a client machine didn't have a value in $home.
Quite old topic. But I want to give my 2 cents...
I've slightly modified tomasz86 solution, to look in the old style "Shell Folders" instead of "User Shell Folders", so i don't need to expand the envvar %userprofile%
Also there is no dependency from powershell/vbscript/etc....
for /f "usebackq tokens=2,3*" %%A in (`REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Desktop"`) do if %%A==REG_SZ set desktopdir=%%B
echo %desktopdir%
Hope it helps.
TL;DR
%HOMEDRIVE%%HOMEPATH%\Desktop seems to be the safest way.
Discussion
Assumptions about which drive a thing is on are quite fragile in Windows as it lacks a unified directory tree where mounts would map to directories internally. Therefore the %HOMEDRIVE% variable is important to reference to make sure you're on the right one (it isn't always C:\!).
Non-English locales will usually have localized names for things like "Desktop" and "Pictures" and whatnot, but fortunately they are all aliases that point to Desktop, which seems to be the underlying canonical directory name regardless of locale (we use this safely here in Japan, Thailand, Israel and the US).
The big quirk comes with determining whether %UserProfile% points to the user's actual profile base dir, or their Desktop or somewhere completely different. I'm not really a Windows dev, but what I've found is the profile dir is for settings, but the %HOMEPATH% is for the user's own files, so this points to the directory root that leads to Desktop/Downloads/Pictures/etc. This tends to make %HOMEDRIVE%%HOMEPATH%\Desktop the safest way.
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.