I used wmic to get the version of a EXE stored in a variable.
It works fine when I execute it from CMD (that I ran as Admin) but when executed either in a .cmd or .bat files (even when ran as admin) the variable is not populated.
This works directly in CMD:
set "npver="&for /F "tokens=2delims==" %a in ('wmic datafile where "Name='c:\\Windows\\System32\\notepad.exe'" get version /format:list') do set "npver=%a"
When I created the .cmd file, I doubled the % signs.
You forgot to echo the variable with the command echo %npver%
With Command line :
set "npver="&for /F "tokens=2delims==" %a in ('wmic datafile where "Name='c:\\Windows\\System32\\notepad.exe'" get version /format:list') do set "npver=%a"& echo %npver%
With a batch file, you should escape the sign percent % by adding another one %%
and your code should works now with a batch file like this :
Batch File :
#echo off
set "npver="&for /F "tokens=2delims==" %%a in ('wmic datafile where "Name='c:\\Windows\\System32\\notepad.exe'" get version /format:list') do set "npver=%%a"
echo %npver%
pause
EDIT : Get_File_Version.bat
Here is another code in batch more elaborated to get file version of any Application from file list using WMIC.
#echo off
Mode 75,3 & color 9E
Title Get File Version of any Application from file list using WMIC by Hackoo
::******************************************************************************
REM Just Change this Variable in your case and the script will do the rest (-_°)
Set "RootFolder=%ProgramData%"
::******************************************************************************
:Main
#for %%a in ("%RootFolder%") do set "FolderName=%%~na"
Set "File_Version_List=%~dp0%FolderName%_File_Version_List.txt"
Set "ErrorFile=%~dp0%FolderName%_Error.txt
Set Extensions="*.exe" "*.dll"
If exist "%ErrorFile%" Del "%ErrorFile%"
If exist "%File_Version_List%" Del "%File_Version_List%"
echo(
echo Please wait a while ... Process to get file version ...
set "BuildLineWith=call :BuildLine "
setlocal enabledelayedexpansion
CD /D "%RootFolder%"
#for /f "delims=" %%F in ('Dir /b /s %Extensions%') do (
set "Version="
Call :Get_AppName "%%F" AppName
Call :Add_backSlash "%%F"
Call :GetVersion !Application! Version
Call :Remove_backSlash !Application!
If defined Version (
(
echo !Application!
echo !AppName! ==^> !Version!
%BuildLineWith%*
)>> "%File_Version_List%"
) else (
(
echo Version is not defined in !Application!
%BuildLineWith%#
)>> "%ErrorFile%"
)
)
If Exist "%ErrorFile%" Start "" "%ErrorFile%"
If Exist "%File_Version_List%" Start "" /MAX "%File_Version_List%" & Exit
::*******************************************************************
:GetVersion <ApplicationPath> <Version>
Rem The argument %~1 represent the full path of the application
Rem without the double quotes
Rem The argument %2 represent the variable to be set (in our case %2=Version)
FOR /F "tokens=2 delims==" %%I IN (
'wmic datafile where "name='%~1'" get version /format:Textvaluelist 2^>^nul'
) DO FOR /F "delims=" %%A IN ("%%I") DO SET "%2=%%A"
Exit /b
::*******************************************************************
:Add_backSlash <String>
Rem Subroutine to replace the simple "\" by a double "\\" into a String
Set "Application=%1"
Set "String=\"
Set "NewString=\\"
Call Set "Application=%%Application:%String%=%NewString%%%"
Exit /b
::*******************************************************************
:Remove_backSlash <String>
Rem Subroutine to replace the double "\\" by a simple "\" into a String
Set "Application=%1"
Set "String=\\"
Set "NewString=\"
Call Set "Application=%%Application:%String%=%NewString%%%"
Exit /b
::*******************************************************************
:Get_AppName <FullPath> <AppName>
Rem %1 = FullPath
Rem %2 = AppName
for %%i in (%1) do set "%2=%%~nxi"
exit /b
::*******************************************************************
:BuildLine
REM Thanks to ImDeepWithWindows for this nice trick of BuildLine
set "LineChar=%1"
if "%LineChar%"=="" set "LineChar=_"
for /f "tokens=2 skip=4" %%A in ('mode con: /status') do set "WindowColumns=%%A" & goto :GotColumnCount
:GotColumnCount
set "CharLine="
setlocal EnableDelayedExpansion
for /L %%A in (1,1,%WindowColumns%) do set "CharLine=!CharLine!!LineChar:~0,1!"
setlocal DisableDelayedExpansion
endlocal
echo %CharLine%
goto :eof
::*******************************************************************
Related
I am trying to embed the below command line into VBA:
for /f "skip=10 delims=" %%A in ('dir /a:-d /b /o:-d /t:c *.log ^2^>nul') do if exist "%%~fA" del "%%~fA
What I tried was:
Set objShell = CreateObject("WScript.Shell")
cmdLine = "cmd /k for /f ""skip=2 delims="" %%A in ('dir /a:-d /b /o:-d /t:c *.xls ^2^>nul') do if exist ""%%~fA"" del ""%%~fA"""
retVal = objShell.Run(cmdLine, 1, True)
It didn't work.
However, if I saved the code as .cmd, it worked.
Finally, I found the issue. It's not about the single quote.
You just need to change %%A into %A. However, if you save the code in .bat/.cmd, %%A works.
It is very finicky dealing with command line.
I have a batch file (Windows command line) that creates a VBS file, runs it, and that in turn re-launches the cmd.exe program in elevated mode so that I can copy a file to the System32 folder.
If I run this batch file manually, all goes according to plan, but if I run it from a VBA Excel macro the batch file gets stuck in an infinite loop, even after the UAC prompt has appeared and I have allowed elevated access. Am I calling the batch file incorrectly from VBA?
I'm fine with VBA, OKish with windows CMD, but haven't often used the two together.
I've tried the following statements in my macro, all 3 have the same result:
Shell Environ("USERPROFILE") & "\Desktop\TEMP.bat"
CreateObject("WScript.Shell").Run "CMD /C %USERPROFILE%\Desktop\TEMP.bat", 0, False
Debug.Print CreateObject("WScript.Shell").Exec("CMD /C %USERPROFILE%\Desktop\TEMP.bat").StdOut.ReadAll
For what it's worth, this is the Batch file code:
#ECHO OFF
:----------------------
>NUL 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
IF '%ERRORLEVEL%' NEQ '0' (
GOTO UACPrompt
) ELSE ( GOTO gotAdmin )
:UACPrompt
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%TEMP%\getadmin.vbs"
ECHO UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%TEMP%\getadmin.vbs"
"%TEMP%\getadmin.vbs"
EXIT /B
:gotAdmin
IF EXIST "%temp%\getadmin.vbs" ( DEL "%TEMP%\getadmin.vbs" )
PUSHD "%CD%"
CD /D "%~dp0"
:----------------------
:: < REST OF SCRIPT HERE - NOT RELEVANT TO QUESTION >
And this is what's in the VBS file:
Set UAC = CreateObject("Shell.Application")
UAC.ShellExecute "C:\Users\SO\Desktop\TEMP.bat", "", "", "runas", 1
Any pointers/suggestions welcome. Thanks in advance.
I had faced the same problem, and below code solved it. Howerver, the problem is Shell doesn't have bWaitOnReturn option.
Dim Foldername As String
Foldername = "C:\WorkspaceRFT\RMS\command.bat"
Shell "C:\WINDOWS\explorer.exe """ & Foldername & "", vbNormalFocus
So I have batch file that contains series of commands. (about 10) -
I've decided that I would like to create simple gui for this tool - simply one button that would execute commands one after another (when command A is finished command B starts)
Thing is that I do not want to use SendKey method, I am looking for a way that would not even show command prompt window. Is there any way to achieve this?
I am obviously beginner, so any help is welcome :).
Thank you very much!
This is part of the batch file that I somehow need to "translate" to VBA code.
wevtutil epl Application %temp%\Sysinfo\AppLog.evtx
wevtutil epl System %temp%\Sysinfo\SystemLog.evtx
takeown /f %temp%\Sysinfo /r /d y
icacls %temp%\Sysinfo /grant administrators:F /T
set FILETOZIP=%temp%\Sysinfo
set TEMPDIR=%temp%\Zip
rd /s /q %TEMPDIR%
mkdir %TEMPDIR%
copy %FILETOZIP% %TEMPDIR%
echo Set objArgs = WScript.Arguments > _zipIt.vbs
echo InputFolder = objArgs(0) >> _zipIt.vbs
echo ZipFile = objArgs(1) >> _zipIt.vbs
echo CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" ^& Chr(5) ^& Chr(6) ^& String(18, vbNullChar) >> _zipIt.vbs
echo Set objShell = CreateObject("Shell.Application") >> _zipIt.vbs
echo Set source = objShell.NameSpace(InputFolder).Items >> _zipIt.vbs
echo objShell.NameSpace(ZipFile).CopyHere(source) >> _zipIt.vbs
echo wScript.Sleep 2000 >> _zipIt.vbs
CScript _zipIt.vbs %TEMPDIR% %userprofile%\Desktop\Systeminfo.zip
CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False
Above runs anything passed on the command line in a hidden window.
& seperates commands on one line
cmd /c dir&time /t%date /t%type c:\windows\win.ini&echo hello
Is there a way to do this purely in a .bat file?
The purpose is to launch iexplore.exe, then kill just that instance when it's finished.
Here's what I use:
#echo off
rem there is a tab in the file at the end of the line below
set tab=
set cmd=javaw -jar lib\MyProg.jar
set dir=%~dp0
echo Starting MyProg
set pid=notfound
for /F "usebackq tokens=1,2 delims=;=%tab% " %%i in (
`wmic process call create "%cmd%"^, "%dir%"`
) do (
if /I %%i EQU ProcessId (
set pid=%%j
)
)
echo %pid% > MyProg.pid
The directory is set to the directory that the cmd file is located in. Change dir to alter that. Modify cmd to change which command is run.
If you want a stop.cmd that kills it, it would look like this
#echo off
for /F %%i in (%~dsp0MyProg.pid) do taskkill /F /PID %%i
del %~dsp0MyProg.pid
you can use vbscript, here's an example creating notepad, then terminating it using its pid
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objStartup = objWMIService.Get("Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
errReturn = objProcess.Create("notepad.exe", null, objConfig, PID)
If errReturn = 0 Then
WScript.Echo "Process ID is: " & PID
End If
WScript.Echo "Ready to kill process: " & PID & "? [Y|y]"
Do While Not WScript.StdIn.AtEndOfLine
strInput = strInput & WScript.StdIn.Read(1)
Loop
If LCase(strInput) = "y" Then
WScript.Echo "Select * from Win32_Process Where ProcessId = '" & PID & "'"
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where ProcessId = '" & PID & "'")
For Each objProcess in colProcessList
objProcess.Terminate()
Next
End If
save as myscript.vbs and on command line
c:\test> cscript /nologo myscript.vbs
A slight variation on the answer provided by #kybernetikos since it has a parsing issue. Note the line if %%j gr 0 (
#echo off
rem there is a tab in the file at the end of the line below
set tab=
set cmd=javaw -jar lib\MyProg.jar
set dir=%~dp0
echo Starting MyProg
set pid=notfound
for /F "usebackq tokens=1,2 delims=;=%tab% " %%i in (
`wmic process call create "%cmd%"^, "%dir%"`
) do (
if %%j gtr 0 (
set pid=%%j
)
)
echo %pid% > MyProg.pid
Most often you do know what task you start - in this case, which page iexplorer shall show.
So how about
taskkill /FI "Windowtitle eq *yourpagetitle*"
It will kill all instances of something showing your page title, but with a specific title most often there should be exactly one.
Tom
Ummm, TaskList & TaskKill?!
For some reason your approach of getting process id did not work for me, but since I'm expert in batches, I've coded my own approach, attaching here:
#echo off
call:AsyncCmd
rem call:AsyncCmd "echo hello world"
rem call:AsyncCmd "call build.bat"
exit /b
rem ------------------------------------------------------------------------------------------
rem Starts asynchronous command execution
rem %1 is command, if empty - only aborts existing build.
rem ------------------------------------------------------------------------------------------
:AsyncCmd
if exist %~dp0SetupBuild_Completed.txt (
del /f %~dp0SetupBuild_Pid.txt >nul 2>&1
del /f %~dp0SetupBuild_Completed.txt >nul 2>&1
)
if not exist %~dp0SetupBuild_Pid.txt goto lStartProc
rem --------------------------------------------------
rem Abort build process
rem --------------------------------------------------
set /p pid=<%~dp0SetupBuild_Pid.txt
echo Cancelling setup build process, process id %pid%
pskill -t %pid%
del /f %~dp0SetupBuild_Pid.txt >nul 2>&1
:lStartProc
if "%~1" == "" exit /b 0
rem --------------------------------------------------
rem Starts asyncronous build process
rem --------------------------------------------------
set dir=%~dp0
set dir=%dir:~0,-1%
for /f "tokens=2 delims==; " %%a in ('wmic process call create "cmd /c mincon.exe && %~1 && echo 1>%~dp0SetupBuild_Completed.txt"^, "%dir%" ^| findstr /r "ProcessId"') do set pid=%%a
echo Setup build started, process id: %pid%
echo %pid%>%~dp0SetupBuild_Pid.txt
exit /b 0
PowerShell can be used for this:
powershell -executionPolicy bypass -command "& {$process = start-process $args[0] -passthru -argumentlist $args[1..($args.length-1)]; exit $process.id}" notepad test.txt
echo Process ID of new process: %errorlevel%
I think you can't do that with simple command line utilities, as IE actually spawns child processes for each tab, i.e. if IE is not yet running you would get one parent IE process and a child process for the tab, and if IE is already running you would simply get a single child process.
It will be even quite tricky when you write your own tool to kill IE because when you kill a child (tab) process, IE will automatically recover this tab.
See also this related question: How to obtain process of newly created IE8 window? (though there is no good answer there).
I would like a batch file that can register a user into itself.
something like:
#echo off
echo Choose an option:
echo 1:Register
echo 2:Login
Set option=
set /p option=Your option:
if %option%==1 goto reg
if %option%==2 goto login
...
:reg
--The registration script--
goto login
...
:login
Set usr=
set /p usr=Username:
if %usr%== goto pass
echo False username!
#pause
goto login
...
:pass
Set passw=
set /p passw=Password:
if %passw%== goto success
echo False password!
#pause
goto login
So... something like that. 'if %passw%== "" and if %usr%== ""' === it should automatticly make that at registration.
It will be nice if more than 1 people could register.
To test for an empty string, put quotes around both sides:
if "%usr%"==""
To append to a text file, use >>
echo %usr%:%pass% >> passwd.txt
To loop over the contents of a file, use for /f:
for /f "delims=: tokens=1,2" %%x in (passwd.txt) do (
if "%%x"=="%usr%" then (
set usrfound=true
)
)
if "%usrfound%"=="" then (
rem Register user
) else (
rem Check password and succeed/fail
)
During testing or debugging, make sure echo is on. If you want to set and test a variable inside a for loop or other multiline statement, put this near the start of the file:
setlocal enabledelayedexpansion
and any time you need to read a variable that might have changed inside the block, use !var! instead of %var%.
Hmmm. This is what i found out by some help:
#echo off
title REGISTERANDLOGIN
if exist programbase.dll goto login
if not exist programbase.dll goto register
:register
title Register
echo Register
echo.
echo Please fill in the blanks.
echo.
Set usrname=
set /p usrname=Username:
Set passw=
set /p passw=Password:
echo %usrname%>> programdata.dll
echo %passw%>> programbase.dll
goto login
:login
:begin
set usr=
set /p usr=Enter your username:
if {%usr%}=={} goto :begin
set authenticated=
for /f "tokens=*" %%a in (programdata.dll) do (
if {%%a}=={%usr%} set authenticated=true
)
if not defined authenticated (echo Invalid Username & goto :begin)
:passwo
set pass=
set /p pass=Enter your password:
if {%pass%}=={} goto :begin
set authenticated=
for /f "tokens=*" %%a in (programbase.dll) do (
if {%%a}=={%pass%} set authenticated=true
)
if not defined authenticated (echo Invalid password & goto :begin)
:loggedin
cls
echo Welcome.
#pause
exit /b 0
I wonder if this will work:
# echo off
goto username
:username
echo Hello, please log in with your user ID or type "reg" to register.
echo Username:
set /p user
if %user%== username(s)here goto password
if %user%==reg goto register
if not defined user (
cls
echo Bad username!
pause
exit
)
Then carry out the rest of the program. I'd try this, and if it doesn't work, tell me about it!
You can try this one . . . I wrote a batch file that has a login & signup module. It creates a file where accounts created are stored. When logged in, special features are included like "Color Changer" and "TicTacToe". The TicTacToe is NOT mine, I got it from
www.screwthelotofyou.webs.com/files/ . This file and the Color Changer were mine.
"Reproduce, edit and distribute all you want. As if I could stop you." - ScrewTheLotofYou
I can't paste the code here, it's too long . . . Link: http://www.mediafire.com/?kwzzvk24nuze8fq
Hope it worked. :D ~ meilviruz99
Found some seriously evil tricks on this web site, including:
ECHO Enter some input, and press Enter when ready . . .
ECHO ←[13;0;64;13p
COPY CON USRINPUT.TMP
ECHO ←[13;13p
CLS
ECHO You typed:
TYPE USRINPUT.TMP
Which uses ANSI key translation to change Enter into CTRL-Z.
I couldn't quite say I fully understand your question, but if in doubts about anything related to batch scripting, I could recommend checking out this website this website.
The tutorial is really exhaustive, easy to follow and has helped me a number of times before.
#echo off
if exist "%userprofile%\documents\Login\Accounts" goto start0
if not exist "%userprofile%\documents\Login\Accounts" md "%userprofile%\documents\Login\Accounts"
:start0
title Login
color 02
cls
echo ---------------------------------
echo Login.
echo ---------------------------------
echo.
echo.
echo.
echo 1.Create New Username.
echo 2.Log in.
echo.
echo.
echo.
set /p A=Choice:
IF '%A%' == '1' GOTO NewUser0
IF '%A%' == '2' GOTO Login0
IF NOT '%A%' == '1' GOTO start0
:NewUser0
cls
color 02
cd "%userprofile%\documents\Login\Accounts"
set /p newuser=New Username:
IF EXIST %newuser%.bat GOTO inval0
set /p newpass=New Password:
echo set realusername=%newuser% >> %newuser%.bat
echo set password=%newpass% >> %newuser%.bat
IF EXIST %newuser%.bat GOTO NewUser1
IF NOT EXIST %newuser%.bat GOTO NewUser2
:NewUser1
echo Your Account Has Been Created Successfully. Press An Key To Continue.
pause >nul
GOTO start0
:NewUser2
cls
color 0c
del /f /q %newuser%.bat
echo ERROR!Account Could Not Be Created For Unknown Reasons.Press Any Key To Continue
pause >nul
GOTO start0
:Login0
cls
color 02
cd "%userprofile%\documents\Login\Accounts"
echo Login.
echo.
echo.
echo.
echo.
set /p loguser=Username:
IF NOT EXIST %loguser%.bat GOTO inval1
:Login1
set /p logpass=Password:
call %loguser%.bat
if %logpass% == %password% goto success0
goto invalid2
:inval0
cls
color 0c
echo Desired Username Already Exists. Press Any Key To Continue.
pause >nul
GOTO start0
:inval1
cls
color 0c
echo Desired Username Does NOT Exist. Press Any Key To Continue.
pause >nul
GOTO start0
:invalid2
cls
color 0c
echo Invalid Password. Press Any Key To Continue.
pause >nul
cls
color 02
echo Login.
echo.
echo.
echo.
echo.
echo Username:%loguser%
GOTO Login1
:Success0
cls
color 02
title End Of My Script
echo You Successfully Logged In.
echo Here Is Where You Continue The Script.
ping localhost -n 3 >nul
echo.
echo.
echo.
echo Press Any Key To Exit.
pause >nul
exit
Check out this incredibly simple chatting program:
#echo off
cls
echo #prompt set date=$d$_set time=$t$h$h$h > {a}.bat
%comspec% /e:2048 /c {a}.bat > {b}.bat
for %%v in ({b}.bat del) do call %%v {?}.bat
:LoGINSCR
ECHO Euronet MessageBoard
ECHO v1.0 [BETA]
goto LOGIN
:LOGIN
ECHO.
set/p user=Login As:
if %user%==Eugene goto PASSWORD
if %user%==Toxic goto PASSWORD
if %user%==Plague goto PASSWORD
if %user%==Jason goto PASSWORD
goto LOGIN
:PASSWORD
set/p pass=Password:
if %pass%==$euronet$ goto SYSTEM
goto LOGIN
:SYSTEM
ECHO Welcome to Euronet MessageBoard, %user%.
goto INPUTMAIN
:INPUTMAIN
ECHO.
set/p main=%user%/chat:
if %main%==help goto HELP
if %main%==join goto JOIN
if %main%==quit goto EXIT
if %main%==ic goto IC
goto ERROR
:IC
ping google.com
PAUSE
ping wikipedia.org
PAUSE
ping facebook.com
PAUSE
ipconfig
PAUSE
goto INPUTMAIN
:ERROR
ECHO [ERROR] No command found ("%main%")
goto INPUTMAIN
:HELP
ECHO Type help to show the help page.
ECHO Type join to join board
ECHO Type quit to exit MessageBoard
ECHO Type ic for internet check
ECHO After you joined the board, you can update
ECHO your screen by pressing "Shift & 6".
goto INPUTMAIN
:JOIN
ECHO.
set/p mesgc=Enter your message:
ECHO %user% [%time%] - %mesgc% >> messg1
goto TRAFFIC
:TRAFFIC
cls
TYPE messg1
goto JOIN
:CLS
cls
goto TRAFFIC
:EXIT
exit
It uses one file, but multiple users could run the bat file and connect to the file. It works by looping the TYPE and set/p commands repeatedly. Although it couldn't update the chat list by itself, you could update it by pressing Shift and 6, and hitting Enter.
Why not just compare input to a user file?
make a file for each user and maybie get a encryption and decryption program to run automaticly for max security.
Batch is a verry simple launguage. just mess around with it for a while.
I'm decently proud of this :)
This has two different files: login.bat which handles the login and login2.bat which handles the registration.
login.bat:
#echo off
choice /c:RL /m "Choose an option: Register (R) or Login (L).:
if errorlevel 2 goto login
if errorlevel 1 goto register
:register
start /wait C:\[path]\login2.bat
cls
goto login
:in
cls
echo Welcome %u%
echo.
echo Bla Bla Bla or start "a program"
pause
exit
:login
set /p u=Username
set /p p=Password
and login2.bat:
#echo off
:a
set /p a="Choose a Username"
set /p b="Choose a Password"
echo.
choice /m "Are you sure you would like your Username to be %a% and your Password to be %b%?"
if errorlevel 2 goto a
set q="if %%u%% equ %a% if %%p%% equ %b% goto in"
for /f "tokens=*" %%I in (%q%) do set m=%%I
echo %m% >>C:\[path]\login.bat
exit
The reason why :in, the label which handles what happens after you login successfully has to be in the middle instead of at the end of login.bat is so that the username/password combinations could be appended to the :login label. Obviously you could add other embellishments and change the name of the files, but this is my basic design. I like how short and comprehensible these are. And they work like a charm 100% of the time.
Hope this helps!
I'm not providing full source code because all of you probably know how to do this.
A really easy way to do what you're asking is to just have a registration and a login page that detects files. Just make a couple directories like userSaves or passSaves for example. Then you have the system just detect whether or not the files exist on login:
:page
set /p usr=Username:
if exist mydir\LoginProgram\saves\userSaves\%usr% (
echo Valid Username.
pause
goto passentry
cls
) else (
echo Invalid Username.
pause
goto page
cls
)
:passentry
cls
set /p pass=Password:
if exist mydir\LoginProgram\saves\passSaves\%pass% (
echo Valid Password. Welcome!
pause
goto whateverpage
cls
) else (
echo Invalid Password. Login failed.
pause
goto page
cls
)
Super simple code. Just do the same thing for registration.