Batch making an UN-installer for a program - batch-file

I have this code to uninstall my software:
#echo off
Taskkill /f /im wscript.exe 2>> Log.txt
If exist "%Temp%\done.vbs" (
Attrib -R -S -H "%Temp%\done.vbs"
If exist "%Temp%\done.vbs" (
Echo Could not delete file "%Temp%\done.vbs"
)
)
> "%Temp%\done.vbs" ECHO x=msgbox("Uninstalling" ,6, "Chip-set")
start "" wscript "%temp%\done.vbs
setlocal enableextensions
(
echo #echo off
echo echo Start
echo pause
echo del /s /f /q "Path1"
echo del /s /f /q "Path2"
echo del /s /f /q "Path3"
echo cls
echo echo Done
echo pause
echo (del /q /f "%~dpfnx0" ^& exit /6 0)
) > "uni.bat"
uni.bat
Taskkill /f /im wscript.exe 2>> Log.txt
If exist "%Temp%\done.vbs" (
Attrib -R -S -H "%Temp%\done.vbs"
If exist "%Temp%\done.vbs" (
Echo Could not delete file "%Temp%\done.vbs"
)
)
> "%Temp%\done.vbs" ECHO x=msgbox("Uninstalled" ,6, "Chip-set")
start "" wscript "%temp%\done.vbs
But it doesn't seem to work and part to the problem is that the uni.bat that is meant to appear doesn't can any one tell me what it wrong.

You have to escape that last ) see below:
echo (del /q /f "%~dpfnx0" ^& exit /6 0^)

Related

Echo adding a random value

I have a batch file that create another batch file.
I need to add inside the echo a random function to have numbers from 1 to 6.
My batch code (works perfectly)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::: Batch Code :::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#echo off
(for /f "usebackq delims=" %%a in ("D:\Program files\Openvpn\openvpn_configuration_list_for_clicks.csv") do (
echo :::: Start Of The Command Block ::::
echo/
echo MOVE /Y "D:\Program files\Openvpn\config_to_check\%%~NXa" "D:\Program files\Openvpn\config\"
echo START "" "C:\Program Files\OpenVPN\bin\openvpn-gui.exe" --connect %%~NXa
echo PING -n 30 localhost ^>NUL 2^>^&1
echo PING -n 5 www.wikipedia.org^|FIND /I "TTL"^>NUL
echo IF NOT "%%ERRORLEVEL%%"=="1" ^(
echo rundll32 user32.dll,MessageBeep 0x00000010L
echo start "" "D:\Program files\Firefox Esr\FirefoxPortable.exe"
echo TIMEOUT /T 60 /NOBREAK ^>NUL
echo goto search_%%a
echo ^)
echo :search_%%a
echo tasklist /FI "IMAGENAME eq firefox.exe" 2^>NUL ^| find /I /N "firefox.exe"^>NUL
echo if "%%ERRORLEVEL%%"=="0" ^(
echo TIMEOUT /T 60 /NOBREAK ^>NUL
echo goto search_%%a
echo ^)
echo if "%%ERRORLEVEL%%"=="1" ^(goto continue_%%a^)
echo :continue_%%a
echo taskkill.exe /F /IM openvpn.exe
echo taskkill.exe /F /IM openvpn-gui.exe
echo MOVE /Y "D:\Program files\Openvpn\config\%%~NXa" "D:\Program files\Openvpn\config_to_check\"
echo/
echo :::: End Of The Command Block ::::
echo/
echo/
echo/
)) > "D:\Program files\Openvpn\final.bat"
(echo exit) >> "D:\Program files\Openvpn\final.bat"
openvpn_configuration_list_for_clicks.csv (list of vpn)
vpn1.ovpn
vpn2.ovpn
vpn4.ovpn
vpn8.ovpn
output final.bat without random function (works perfectly)
:::: Start Of The Command Block ::::
MOVE /Y "D:\Program Files\Openvpn\config_to_check\vpn1.ovpn" "D:\Program Files\Openvpn\config\"
START "" "C:\Program Files\OpenVPN\bin\openvpn-gui.exe" --connect vpn1.ovpn
PING -n 30 localhost >NUL 2>&1
PING -n 5 www.wikipedia.org|FIND /I "TTL">NUL
IF NOT "%ERRORLEVEL%"=="1" (
rundll32 user32.dll,MessageBeep 0x00000010L
start "" "D:\Program Files\Firefox Esr\FirefoxPortable.exe"
TIMEOUT /T 60 /NOBREAK >NUL
goto search_vpn1.ovpn
)
:search_vpn1.ovpn
tasklist /FI "IMAGENAME eq firefox.exe" 2>NUL | find /I /N "firefox.exe">NUL
if "%ERRORLEVEL%"=="0" (
TIMEOUT /T 60 /NOBREAK >NUL
goto search_vpn1.ovpn
)
if "%ERRORLEVEL%"=="1" (goto continue_vpn1.ovpn)
:continue_vpn1.ovpn
taskkill.exe /F /IM openvpn.exe
taskkill.exe /F /IM openvpn-gui.exe
MOVE /Y "D:\Program Files\Openvpn\config\vpn1.ovpn" "D:\Program Files\Openvpn\config_to_check\"
:::: End Of The Command Block ::::
I need a solution to have a random number from 1 to 6 in path inside echo
"D:\Program Files\Firefox Esr 2\FirefoxPortable.exe"
or
"D:\Program Files\Firefox Esr 5\FirefoxPortable.exe"
or
"D:\Program Files\Firefox Esr 6\FirefoxPortable.exe"
The code without a random function works very well and generates output correctly, I need to insert a random function inside the code that does not send the output generation into error.
The random function need to calculate for every loop to have a new random number for every loop
Let me step through my comment with some examples.
Your initial code was escaping opening parentheses unnecessarily and should have looked more like this:
Echo :::: Start Of The Command Block ::::
Echo/
Echo Ping -n 30 localhost ^>Nul 2^>^&1
Echo Ping -n 5 www.facebook.com^|Find /I "TTL"^>Nul
Echo If Not "%%ErrorLevel%%"=="1" (
Echo Rundll32 User32.dll,MessageBeep 0x00000010L
Echo Set /A num=(%%RANDOM%% %%%% 6^^^) + 1
Echo Start "" "D:\Program Files\Firefox Portable %%num%%\FirefoxPortable.exe"
Echo Timeout 60 /NoBreak ^>Nul
Echo ^)
Echo/
Echo :search
However, you are setting a variable and trying to use it within the same If block, this can be fixed in a number of ways:
Use a pseudo Call statement:
Echo :::: Start Of The Command Block ::::
Echo/
Echo Ping -n 30 localhost ^>Nul 2^>^&1
Echo Ping -n 5 www.facebook.com^|Find /I "TTL"^>Nul
Echo If Not "%%ErrorLevel%%"=="1" (
Echo Rundll32 User32.dll,MessageBeep 0x00000010L
Echo Set /A num=(%%RANDOM%% %%%% 6^^^) + 1
Echo Call Start "" "D:\Program Files\Firefox Portable %%%%num%%%%\FirefoxPortable.exe"
Echo Timeout 60 /NoBreak ^>Nul
Echo ^)
Echo/
Echo :search
Enable delayed expansion: (this example assumes that delayed expansion isn't already enabled in the script doing the Echoing)
Echo :::: Start Of The Command Block ::::
Echo/
Echo Ping -n 30 localhost ^>Nul 2^>^&1
Echo Ping -n 5 www.facebook.com^|Find /I "TTL"^>Nul
Echo If Not "%%ErrorLevel%%"=="1" (
Echo Rundll32 User32.dll,MessageBeep 0x00000010L
Echo Set /A num=(%%RANDOM%% %%%% 6^^^) + 1
Echo SetLocal EnableDelayedExpansion
Echo Start "" "D:\Program Files\Firefox Portable !num!\FirefoxPortable.exe"
Echo EndLocal
Echo Timeout 60 /NoBreak ^>Nul
Echo ^)
Echo/
Echo :search
Enable delayed expansion: (this example assumes that delayed expansion is already enabled in the script doing the Echoing)
Echo :::: Start Of The Command Block ::::
Echo/
Echo Ping -n 30 localhost ^>Nul 2^>^&1
Echo Ping -n 5 www.facebook.com^|Find /I "TTL"^>Nul
Echo If Not "%%ErrorLevel%%"=="1" (
Echo Rundll32 User32.dll,MessageBeep 0x00000010L
Echo Set /A num=(%%RANDOM%% %%%% 6^^^) + 1
Echo SetLocal EnableDelayedExpansion
Echo Start "" "D:\Program Files\Firefox Portable ^!num^!\FirefoxPortable.exe"
Echo EndLocal
Echo Timeout 60 /NoBreak ^>Nul
Echo ^)
Echo/
Echo :search
Restructure the code in order not to have an unnecessary If block (preferred):
Echo :::: Start Of The Command Block ::::
Echo/
Echo Ping -n 30 localhost ^>Nul 2^>^&1
Echo Ping -n 5 www.facebook.com^|Find /I "TTL"^>Nul
Echo If "%%ErrorLevel%%"=="1" GoTo search
Echo Rundll32 User32.dll,MessageBeep 0x00000010L
Echo Set /A num=(%%RANDOM%% %%%% 6^) + 1
Echo Start "" "D:\Program Files\Firefox Portable %%num%%\FirefoxPortable.exe"
Echo Timeout 60 /NoBreak ^>Nul
Echo/
Echo :search
All of the above examples assume that the code shown is inside a parenthesised block, similar to (code above)>"another.bat" or >"another.cmd" (code above)
[Edit /]
Here's some code to incorporate the additional stuff you've now posted. I have utilised methd 4. from above to remove the unnecessary If blocks. It should also incorporate the randomisation function you require, which is the same as previously posted and compatible with your batch file.
#Echo Off
(For /F "UseBackQ Delims=" %%A In (
"D:\Program Files\OpenVPN\openvpn_configuration_list_for_clicks.csv") Do (
Echo #Move /Y "D:\Program Files\OpenVPN\config_to_check\%%~nxA" "D:\Program Files\OpenVPN\config"
Echo #Start "" "C:\Program Files\OpenVPN\bin\OpenVPN-GUI.exe" --connect %%~nxA
Echo #Timeout 30 /NoBreak^>Nul 2^>^&1
Echo #Ping -n 5 www.wikipedia.org^|Find /I "TTL"^>Nul^|^|GoTo search_%%A
Echo #Rundll32 User32.dll,MessageBeep 0x00000010L
Echo #Set "num="
Echo #Set /A num=(%%RANDOM%% %%%% 6^) + 1
Echo #Start "" "D:\Program Files\Firefox ESR %%num%%\FirefoxPortable.exe"
Echo #Timeout 60 /NoBreak^>Nul
Echo/
Echo :search_%%A
Echo #TaskList^|Find /I "Firefox.exe"^>Nul^|^|GoTo continue_%%A
Echo #Timeout 60 /NoBreak^>Nul
Echo #GoTo search_%%A
Echo/
Echo :continue_%%A
Echo #TaskKill /F /IM OpenVPN.exe 2^>Nul
Echo #TaskKill /F /IM OpenVPN-GUI.exe 2^>Nul
Echo #Move /Y "D:\Program Files\OpenVPN\config\%%~nxA" "D:\Program Files\OpenVPN\config_to_check"
Echo/))>"final.bat"
Echo #Exit /B>>"D:\Program Files\OpenVPN\final.bat"

Delete files of ftp server in two or more different directories

#echo on
setlocal EnableExtensions DisableDelayedExpansion
#cd /d "%~dp0"
( echo open ftp.xxxxxxxx.com
echo kaxxxxx
echo kaxxxxx
echo ascii
echo cd "dir1/TUN/"
echo mdelete *.txt
echo cd -
echo cd "dir2/TUN2/"
echo mdelete *.txt
echo bye
)> %temp%\ftpdel.dat
ftp -i -s:%temp%/ftpdel.dat
del /f /s /q %temp%\ftprecive.dat >nul 2>nul
pause
I was trying to delete all *.txt files of these both directories, but the script says that i can't change to "dir2/TUN2/"
What's wrong?

Batch file loop issue - ends batch file

I have problem with my batch file.
#echo off
:START
echo Are you ready?
SET logpath=xxx
:COPY
pause
xxx
:FIRST
for /f %%g IN (hostnames.txt) do (
::xcopy "xxx*.*" \\%%g\c$\temp\ /f /s /y /i
echo PC %%g >> %logpath%\xxx
echo %%g > appname.txt
psexec -h \\%%g cmd /c msiexec /i xxx
IF '%ERRORLEVEL%'=='0' (
echo xxx Success! >> %logpath%\xxx.txt
) else (
echo xxx Error is %ERRORLEVEL%. >> %logpath%\xxx.txt
)
psexec -h \\%%g cmd /c msiexec /i xxx
IF '%ERRORLEVEL%'=='0' (
echo xxx Success! >> %logpath%\xxx.txt
) else (
echo xxx Error is %ERRORLEVEL%. >> %logpath%\xxx.txt
)
:SECOND
psexec -h \\%%g cmd /c MsiExec.exe /I{xxx} /passive /norestart
IF '%ERRORLEVEL%'=='0' (
echo test {...-xxx} uninstalled! >> %logpath%\xxx.txt
goto THIRD
)
psexec -h \\%%g cmd /c msiexec /x "{xxx}" /passive /norestart
IF '%ERRORLEVEL%'=='0' (
echo Pierwszy {...-xxx} uninstalled! >> %logpath%\xxx.txt
goto THIRD
)
::Like 15 times uninstalling different apps
:THIRD
for /f %%g in (appname.txt) do taskkill -s %%g -im xxx.exe -f
for /f %%g in (appname.txt) do psexec -h \\%%g cmd /c msiexec /i xxx /passive /norestart
IF '%ERRORLEVEL%'=='0' (
echo xxx Success! >> %logpath%\xxx.txt
) else (
echo xxx. Error is %ERRORLEVEL%. >> %logpath%\xxx.txt
)
for /f %%g in (appname.txt) do psexec -h \\%%g cmd /c regedit /s xxx.reg
for /f %%g in (appname.txt) do psexec -h \\%%g cmd /c del c:\temp\xxx\*.* /f /s /q
echo. >> %logpath%\xxx.txt
echo. >> %logpath%\xxx.txt
)
At first, like You can see in the THIRD section I need to use for /f %%g in (appname.txt) do psexec -h instead of psexec -h, because psexec fails and it's "losing" hostname and this is the only workaround which I have found by myself.
Second thing (most important) is that when batch runs to the end (to the last ")") it stops. Like the first loop for was ended and it doesn't get new hostname from file hostnames.txt
I would be gratefull for any ideas how to make it work

How do I achieve this typing effect?

I want to achieve this typing effect (it isn't enable delay expression / typewriter effect.)
Example of what I want:
How would I achieve this ?
You can do something like that :
#echo off
Call :TypeWriter "http://stackoverflow.com/questions/40011157/how-do-i-fix-this-batch-file-typewriter-effect"
pause && goto Next
::*************************************************************
:TypeWriter
echo(
(
echo strText=wscript.arguments(0^)
echo intTextLen = Len(strText^)
echo intPause = 10
echo For x = 1 to intTextLen
echo strTempText = Mid(strText,x,1^)
echo WScript.StdOut.Write strTempText
echo WScript.Sleep intPause
echo Next
)>%tmp%\%~n0.vbs
#cscript.EXE /noLogo "%tmp%\%~n0.vbs" "%~1"
echo(
exit /b
::**************************************************************
:Next
color 0C
Call :TypeWriter "Deleting Recycled Items..."
Call :TypeWriter "echo del /s /q "C:\$RECYCLE.BIN\*.lnk""
echo del /s /q "C:\$RECYCLE.BIN\*.lnk"
Call :TypeWriter "echo del /s /q "C:\$RECYCLE.BIN\*.pf""
echo del /s /q "C:\$RECYCLE.BIN\*.pf"
Call :TypeWriter "echo rd /s /q "C:\$RECYCLE.BIN\Rar$EXa0.*.*""
echo rd /s /q "C:\$RECYCLE.BIN\Rar$EXa0.*.*"
Call :TypeWriter "echo del /s /q "C:\$RECYCLE.BIN\Rar$EXa0.*.*"
echo del /s /q "C:\$RECYCLE.BIN\Rar$EXa0.*.*"
Call :TypeWriter "echo rd /s /q "C:\$RECYCLE.BIN\Rar$DIa0.*.*""
echo rd /s /q "C:\$RECYCLE.BIN\Rar$DIa0.*.*"
Call :TypeWriter "echo del /s /q "C:\$RECYCLE.BIN\Rar$D.*.*"Ia0"
echo del /s /q "C:\$RECYCLE.BIN\Rar$D.*.*"Ia0
Call :TypeWriter "echo del /s /q "C:\$RECYCLE.BIN\etilqs_*.*""
echo del /s /q "C:\$RECYCLE.BIN\etilqs_*.*"
echo Recycled Items Deleted!
pause>nul & exit
::************************************************
NB : You can change the value as you want of intPause = 10 to go more slower or faster
I had no idea you could do something like this in Batch, but I found some interesting methods. It's limited, but if you want Batch only...
#echo off
call :Sentence Do you understand the words that are coming out of my mouth
call :Sentence Man, nobody understands the words coming out of your mouth!
goto :eof
:Sentence
for %%a in (%*) do (
<nul set /p ".=%%a "
ping -n 1 -w 500 1.1.1.1>nul
shift
)
echo.
goto :eof

Bad syntax in Batch File

It is very late, and I'm tired at looking at this. Could someone explain where I might have bad syntax in this script?
The script looks to see if an old installation exists on a live machine within computers.txt file. If so, it should uninstall it, copy over the new installation, and then install it. If anything fails, log to its respective log file.
#echo off
:CheckifLogsExist
if NOT exist Uninstall.log (
copy /y nul Uninstall.log
) else (
del Uninstall.log && copy /y nul Uninstall.log
)
if NOT exist WMIC.log (
copy /y nul WMIC.log
) else (
del WMIC.log && copy /y nul WMIC.log
)
if NOT exist Copying.log (
copy /y nul Copying.log
) else (
del Copying.log && copy /y nul Copying.log
)
if NOT exist Install.log (
copy /y nul Install.log
) else (
del Install.log && copy /y nul Install.log
)
:checkifalive
for /F %%I IN (computers.txt) DO
(
ping -n 1 %%I
if NOT %errorlevel%==0 echo Machine offline && goto:EOF
:Uninstall
echo "Uninstalling previous version of Symantec Endpoint Protection"
psexec \\%%I -s wmic failfast:on product where name="Symantec Endpoint Protection" call uninstall /nointeractive
if NOT %errorlevel%==0 echo %%I - %errorlevel% >> Uninstall.log
:copy
echo "Finding out which processor is in the machine"
wmic cpu list brief > temp.out
findstr /I "86" temp.out && goto copy86 || goto copy64
if NOT %errorlevel%==0 echo %%I - %errorlevel% >> WMIC.log
:copy86
echo "Copying the installation to the local machine"
copy "C:\installation.exe" \\%%I
if NOT %errorlevel%==0 echo %%I - %errorlevel% >> Copying.log
goto Install86
:copy64
echo "Copying the installation to the local machine"
copy "C:\installation.exe" \\%%I
if NOT %errorlevel%==0 echo %%I - %errorlevel% >> Copying.log
goto Install64
:Install86
echo "Installing upgraded Symantec Endpoint Protection"
psexec \\%%I -s "C:\installation.exe /s"
if NOT %errorlevel%==0 echo %%I - %errorlevel% >> Install.log
goto Finish
:Install64
echo "Installing upgraded Symantec Endpoint Protection"
psexec \\%%I -s "C:\installation.exe /s"
if NOT %errorlevel%==0 echo %%I - %errorlevel% >> Install.log
goto Finish
:Finish
)
Your syntax error is that these need to be on the same line, with a space after do
Note Stephan's comment that you also need to enable delayed expansion or as Vicky says use a subroutine that the forindo command will call
for /F %%I IN (computers.txt) DO
(
#echo off
:clear_logfiles :: Label not needed
:: copy command doesn't care, if the file exists or not, it just (re)creates it with size 0:
copy /y nul Uninstall.log
copy /y nul WMIC.log
copy /y nul Copying.log
copy /y nul Install.log
:checkifalive :: Label not needed
for /F %%I IN (computers.txt) DO ( call DoIt %%i )
echo all done.
goto :eof
REM this is the subroutine
:DoIt
ping -n 1 %1
if NOT %errorlevel%==0 (
echo Machine offline
goto :EOF
)
REM Uninstall
echo "Uninstalling previous version of Symantec Endpoint Protection"
psexec \\%1 -s wmic failfast:on product where name="Symantec Endpoint Protection" call uninstall /nointeractive
if NOT %errorlevel%==0 echo %1 - %errorlevel% >> Uninstall.log
REM copy
echo "Finding out which processor is in the machine"
wmic cpu list brief | findstr /I "86"
:: why checking for 86/64 if the code is exactly the same for both? Anyway - here we go:
if %errorlevel%==0 ( call copy86 ) else ( call copy64 )
goto :eof
:copy86
echo "Copying the installation to the local machine"
copy "C:\installation.exe" \\%1
if NOT %errorlevel%==0 (
echo %1 - %errorlevel% >> Copying.log
) else (
REM Install86
echo "Installing upgraded Symantec Endpoint Protection"
psexec \\%1 -s "C:\installation.exe /s"
if NOT %errorlevel%==0 echo %1 - %errorlevel% >> Install.log
)
goto :eof
:copy64
echo "Copying the installation to the local machine"
copy "C:\installation.exe" \\%1
if NOT %errorlevel%==0(
echo %1 - %errorlevel% >> Copying.log
) else (
REM Install64
echo "Installing upgraded Symantec Endpoint Protection"
psexec \\%1 -s "C:\installation.exe /s"
if NOT %errorlevel%==0 echo %1 - %errorlevel% >> Install.log
)
goto :eof

Resources