Keep batch file from being edited [closed] - batch-file

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 months ago.
Improve this question
Can I lock or set a password to a batch file/script, I have made a script but I don't want people on my work to change it. They must be able to run it but not edit it.
Is this possible and how?
I have search for it but I can't find it. I find all about how to lock PC or something else but not my batch file/script and the Q is not how to hide my script or something but if you whant to edit it, it gives a error or if you click on edit it don't work.

If you don't want them to be able to commit changes to the file, just set the file permissions, only allowing you (or some admin group) to modify the file.
This command will remove inherited ACL entries, grant you full permission, and grant everyone else read permission:
icacls your_file.cmd /inheritance:r /grant youruserid:F /grant everyone:RX

It's not possible however you can use this trick make a c/c++ program that simply call those cmds from system() function. In this case you commands will be hidden to some extent and they won't be able to change it.

One word more about this topic.
It is not possible to avoid that others have access to your Batch file; however, if you want to avoid that others can review the Batch file contents (so they can't modify any part of it) then there are several ways to do that including converting the file to .exe format, although no one of these methods gives complete protection against determined users.
The point here is to use a method simple enough for you, so you may implement it with no problems, but complex enough for others so it dissuade your users to try to break it. I propose a solution based on the Encode procedure for JScript source programs that is not a widely known method, so it may even gives protection against advanced users that have not the appropriate information about it. Here it is:
#if (#CodeSection == #Batch) #then
#echo off
setlocal DisableDelayedExpansion
REM Obfuscate.bat: Obfuscate Batch files
REM Antonio Perez Ayala
if "%~1" equ "" echo Usage: Obfuscate filename.bat & goto :EOF
if not exist "%~1" echo File not found: "%~1" & goto :EOF
set "at=#"
set "pass=%random%"
(
echo %at%if (#Pass == #X%pass%^) #begin
echo #echo off
echo CScript //nologo //E:JScript.Encode "%%~F0" ^> %pass%.bat
echo call %pass%
echo del %pass%.bat
echo exit /B
echo %at%end
echo //**Start Encode**
echo var a = new Array(^);
set "i=0"
for /F "usebackq delims=" %%a in ("%~1") do (
set /A i+=1
set "line=%%a"
setlocal EnableDelayedExpansion
echo a[!i!] = '!line:'=\x27!';
endlocal
)
setlocal EnableDelayedExpansion
echo for ( var i=1; i^<=!i!; ++i ^) WScript.Stdout.WriteLine(a[i]^);
) > "%~N1.tmp"
CScript //nologo //E:JScript "%~F0" "%~N1.tmp"
del "%~N1.tmp"
goto :EOF
#end
// Encode a JScript source file
// Antonio Perez Ayala
var fileToEncode = WScript.Arguments(0);
// Read the source file
var oFSO = WScript.CreateObject("Scripting.FileSystemObject");
var oFile = oFSO.GetFile(fileToEncode);
var oStream = oFile.OpenAsTextStream(1);
var sSourceFile = oStream.ReadAll();
oStream.Close();
// Encode the file
var oEncoder = WScript.CreateObject("Scripting.Encoder");
var sDest = oEncoder.EncodeScriptFile(".js",sSourceFile,0,"")
// Write the encoded version
var sFileOut = fileToEncode.slice(0,-3)+"obf.bat";
var oEncFile = oFSO.CreateTextFile(sFileOut);
oEncFile.Write(sDest);
oEncFile.Close();
Copy this program as Obfuscate.bat and use it giving your Batch file in the parameter; after that, a new file with .obf.bat extension is created that works in the same way than the original file, but with its contents encoded in an unreadable way. For example:
C:\> type test.bat
#echo off
echo Hello World
C:\> Obfuscate test.bat
C:\> type test.obf.bat
#if (#Pass == #X20203) #begin
#echo off
CScript //nologo //E:JScript.Encode "%~F0" > 20203.bat
call 20203
del 20203.bat
exit /B
#end
//**Start Encode**##~^kQAAAA==###&\CMPmP',x⌂APzD.lH`bI###&l]qT,'PE#$nm4W,WW0vI##
#&C$yDP{Pvn1tW~u⌂VsW, KDs9Bp###&6WM~`,\CD,kxqpPk#!x pP_3r~#,⌂Um.k2Oc?ONK;Yc⌂.r
D+SrU⌂`C$bD*i###&kiYAAA==^#~#
C:\> test.obf.bat
Hello World
I tested this method in Windows XP and Windows 8.

Short answer: No
Long answer: No, it's not possible
You can obfuscate it, but you can't hide the source.
Somehow cmd.exe has to execute your batch, so it has to see the commands, but when cmd.exe can see your commands, then a person can see them also.
As you only want to lock the file for editing you can use the both mentioned ways:
Then using attrib could solve it with adding readonly or hidden attributes (like #JanDoggen mentioned).
Or the more secure way by changing the security settings (like #mstth mentioned)
But this will only prevent changes from absolutly noobs.

I tried to make this in batch. I suppose this file could be somewhat helpful, it uses a encrypted password method. You could wrap the batch file into a encrypted exe file, also if you wanted the code obfuscated, possibly even an added byte order mark to make it harder for other people to get your password just ask and I will do that for you. Also you can automatically set the file by doing this ; Go to the "PasswordOptions.bat" file after it is created, set your password, un-hide password files, open then password folder, copy and paste the "Pswrd.Zask" & "Key.Zask" files in a different folder and use the contents for later use, lastly reset your password.
#echo off
title Zask's password encrypted batch file
color 0a
echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
echo º Zask's password encrypted batch file º
echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
echo.
if not exist "C:\Pswrd.Zask\" (
mkdir "C:\Pswrd.Zask\"
if "!errorlevel!" EQU "0" (
goto DirectoryExist
) else (
echo Created the folder "C:\Pswrd.Zask" & timeout /t 5 /nobreak
)
) else (
goto DirectoryExist
)
:DirectoryExist
if exist C:\Pswrd.Zask\Key.Zask (
goto UsernameExist
) else (
goto CreatePasswordScreen
)
:UsernameExist
for /f "Delims=" %%A in (C:\Pswrd.Zask\Password.Zask) do (
set CHECKPASSWORD=%%A
)
for /f "Delims=" %%B in (C:\Pswrd.Zask\Key.Zask) do (
set CHECKKEY=%%B
)
goto PasswordScreen
:CreatePasswordScreen
cls
echo Create a password.
echo.
setlocal EnableDelayedExpansion
set /p "CREATEPASSWORD= Enter password : "
set /p "CREATEKEY= Enter a key number (Choose a number 2-200) : "
set CHAR=0123456789bhfcjrwmudaxopvntzlqeisykg
for /l %%C in (10 1 36) do (
for /f %%D in ("!CHAR:~%%C,1!") do (
set /a MATH=%%C*%CREATEKEY%
for /f %%E in ("!MATH!") do (
set "CREATEPASSWORD=!CREATEPASSWORD:%%D=-%%E!"
)
)
)
echo %CREATEPASSWORD% >> C:\Pswrd.Zask\Password.Zask
attrib C:\Pswrd.Zask\Password.Zask +s +h & echo. & echo Password Created!
echo %CREATEKEY% >> C:\Pswrd.Zask\Key.Zask
attrib C:\Pswrd.Zask\Key.Zask +s +h & echo Username Created!
echo.
if exist "%~dp0ResetPassword.bat" (
del "%~dp0ResetPassword.bat" )
:ResetPassword
set /p "RESETOPTION=Would you like to create the password options file in the current directory (Y/N)? : "
if /i %RESETOPTION%==Y goto ResetOptions
if /i %RESETOPTION%==N goto SkipResetOptions
:ResetOptions
echo #echo off >> PasswordOptions.bat
echo title ResetPassword.bat >> PasswordOptions.bat
echo color 0a >> PasswordOptions.bat
echo :start >> PasswordOptions.bat
echo. >> PasswordOptions.bat
echo echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» >> PasswordOptions.bat
echo echo º This file is used to reset your password, hide it for future purposes or delete it º >> PasswordOptions.bat
echo echo º to avoid other users from removing your password. You have 5 options º >> PasswordOptions.bat
echo echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ >> PasswordOptions.bat
echo echo. >> PasswordOptions.bat
echo echo 1 - Reset password. >> PasswordOptions.bat
echo echo 2 - Open password folder. >> PasswordOptions.bat
echo echo 3 - Unhide files in the password folder. >> PasswordOptions.bat
echo echo 4 - Hide files in the password folder. >> PasswordOptions.bat
echo echo 5 - Exit dialog. >> PasswordOptions.bat
echo echo. >> PasswordOptions.bat
echo set /p "OPTIONS=Chose a number to select that option : " >> PasswordOptions.bat
echo if %%OPTIONS%%==1 goto PasswordReset >> PasswordOptions.bat
echo if %%OPTIONS%%==2 start C:\Pswrd.Zask ^& cls ^& goto start >> PasswordOptions.bat
echo if %%OPTIONS%%==3 attrib C:\Pswrd.Zask\Password.Zask -s -h ^& attrib C:\Pswrd.Zask\Key.Zask -s -h ^& cls ^& goto start >> PasswordOptions.bat
echo if %%OPTIONS%%==4 attrib C:\Pswrd.Zask\Password.Zask +s +h ^& attrib C:\Pswrd.Zask\Key.Zask +s +h ^& cls ^& goto start >> PasswordOptions.bat
echo if %%OPTIONS%%==5 exit >> PasswordOptions.bat
echo. >> PasswordOptions.bat
echo :PasswordReset >> PasswordOptions.bat
echo cls >> PasswordOptions.bat
echo set /p "RESET=Are you sure you want to reset your password (Y/N)? : " >> PasswordOptions.bat
echo if /i %%RESET%%==Y goto ResetPassword >> PasswordOptions.bat
echo if /i %%RESET%%==N goto start >> PasswordOptions.bat
echo cls >> PasswordOptions.bat
echo. >> PasswordOptions.bat
echo :ResetPassword >> PasswordOptions.bat
echo rd /s /q "C:\Pswrd.Zask" >> PasswordOptions.bat
echo echo Password was deleted! >> PasswordOptions.bat
echo pause >> PasswordOptions.bat
echo del %%~n0%%~x0 >> PasswordOptions.bat
echo exit >> PasswordOptions.bat
cls
echo. & echo Created file "%~dp0ResetPassword.bat" & timeout /t 5 /nobreak
:SkipResetOptions
start %~n0%~x0
exit
:PasswordScreen
color 0a
cls
echo Existing User Account.
echo.
setlocal EnableDelayedExpansion
set /p "PASSWORD= Enter Password : "
set /p "KEY= Enter the original encryption key : "
set CHAR=0123456789bhfcjrwmudaxopvntzlqeisykg
for /l %%C in (10 1 36) do (
for /f %%D in ("!CHAR:~%%C,1!") do (
set /a MATH=%%C*%CHECKKEY%
for /f %%E in ("!MATH!") do (
set "CHECKPASSWORD=!CHECKPASSWORD:%%E=%%D!"
)
)
)
for /f %%F in ("!CHECKPASSWORD!") do (
set "CHECKPASSWORD=!CHECKPASSWORD:-=!"
)
if %PASSWORD%==%CHECKPASSWORD% (
goto Operation1True
) else (
goto OperationFalse
)
:Operation1True
if %KEY%==%CHECKKEY% (
goto Operation2True
) else (
goto OperationFalse
)
:OperationFalse
color 0c
echo Password Incorrect!
timeout /t 10 /nobreak
goto PasswordScreen
:Operation2True
cls
echo Password Correct!
echo.
pause
REM YOUR CODE GOES HERE.
REM YOU CAN CONVERT THIS IS INTO A EXE FILE IF WANTED.
REM FREE TO MODIFY ANY CONTENT IN THIS FILE FOR BUSINESS OR PERSONAL REASONS.

You could set an attribute at the beginning of the file like this:
#echo off
attrib +R

If your users are not very sophisticated maybe you can hide your batch file and call it from another one:
One.bat
#echo off
two
Two.bat
#echo off
echo this is 2
pause
Set attributes of two.bat to -h (and maybe -r).
Then call one.bat. Just tested this under Win7 and to my surprise it works.
But this does not solve your issue if the people at your work know how to change file attributes.

Related

Update Currently Running Batch Script

Playing around with my Batch script again. It was brought to my attention that my update routine was not working correctly. Iteration 1 would result in the running script being deleted and not copying the new version from a folder I had selected. Iteration 2 now deletes the old script and copies the new script but with each line of code I change I end up with the currently running script closing, and the new updated script not launching.
Here's a snippet of the Update routine:
:Options
REM I'll set the variable here to what is set elsewhere in the script.
SET VERSION=Version 1.7
CLS
ECHO.
ECHO.
ECHO %VERSION%
ECHO.
ECHO.
ECHO ==================== OPTIONS =====================
ECHO.
ECHO 1. Update Script WIP
ECHO 2. Install entire script to Statup Folder
ECHO 3. Install individual items for auto-launch
ECHO 4. Install Windows Logout feature
ECHO 5. Uninstall
ECHO 6. Change Colors
ECHO 7. Changelog
ECHO.
ECHO =======PRESS 'Q' TO QUIT OR 'B' TO GO BACK========
ECHO.
SET OPTION=
SET /P OPTION=Select an Option:
IF /I '%OPTION%'=='1' GOTO Update
IF /I '%OPTION%'=='2' GOTO Install
IF /I '%OPTION%'=='3' GOTO I_Install
IF /I '%OPTION%'=='4' GOTO I_Logout
IF /I '%OPTION%'=='5' GOTO Uinstall
IF /I '%OPTION%'=='6' GOTO Colors
IF /I '%OPTION%'=='7' GOTO Changelog
IF /I '%OPTION%'=='q' GOTO quit
IF /I '%OPTION%'=='quit' GOTO quit
IF /I '%OPTION%'=='b' GOTO menu
IF /I '%OPTION%'=='back' GOTO menu
ECHO.
ECHO ============INVALID INPUT============
ECHO Please select a number
ECHO or select 'Q' or 'B'.
ECHO ======PRESS ANY KEY TO CONTINUE======
PAUSE > NUL
GOTO Options
:Update
ECHO.
IF EXIST "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\Shortcut Browser *.bat" (
GOTO Update_1
) ELSE (
ECHO You have not installed the script yet. Please install the script first.
)
PAUSE
GOTO Options
:Update_1
IF EXIST "%userprofile%\AppData\Local\Temp\Update.bat" (
GOTO Update_2
) ELSE (
REM Here the main script writes an update script to a batch file
ECHO DEL "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\Shortcut Browser *.bat" > "%userprofile%\AppData\Local\Temp\Update.bat"
REM I replaced the original file location with one on the desktop. The original location was on a network drive, location is confidential.
ECHO COPY "%userprofile\Desktop\Shortcut Browser *.bat" "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup" >> "%userprofile%\AppData\Local\Temp\Update.bat"
ECHO CALL "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\Shortcut Browser *.bat" >> "%userprofile%\AppData\Local\Temp\Update.bat"
ECHO EXIT >> "%userprofile%\AppData\Local\Temp\Update.bat"
)
GOTO Update_2
REM Here the main script calls upon the update script
:Update_2
CALL "%userprofile%\AppData\Local\Temp\Update.bat"
REM The script seems to hang here. Either both the scripts will remain open or close or a combination depending on where CALL and START were used.
PAUSE
GOTO Options
I saw elsewhere I could have used the FC command. I didn't know about it until troubleshooting this problem. I've gotten this far and I feel I'm just missing some small trick to get the new updated script to launch.
If you need any more info let me know. I think I covered everything.
#ECHO OFF
SETLOCAL
TITLE Super Script 5000
:Options
REM I'll set the variable here to what is set elsewhere in the script.
SET VERSION=Version 1.7
CLS
ECHO.
ECHO.
ECHO %VERSION%
ECHO.
ECHO.
ECHO ==================== OPTIONS =====================
ECHO.
ECHO 1. Update Script WIP
ECHO 2. Install entire script to Statup Folder
ECHO 3. Install individual items for auto-launch
ECHO 4. Install Windows Logout feature
ECHO 5. Uninstall
ECHO 6. Change Colors
ECHO 7. Changelog
ECHO.
ECHO =======PRESS 'Q' TO QUIT OR 'B' TO GO BACK========
ECHO.
SET "OPTION="
SET /P "OPTION=Select an Option: "
IF /I "%OPTION%"=="1" GOTO Update
IF /I "%OPTION%"=="2" GOTO Install
IF /I "%OPTION%"=="3" GOTO I_Install
IF /I "%OPTION%"=="4" GOTO I_Logout
IF /I "%OPTION%"=="5" GOTO Uinstall
IF /I "%OPTION%"=="6" GOTO Colors
IF /I "%OPTION%"=="7" GOTO Changelog
IF /I "%OPTION%"=="q" GOTO quit
IF /I "%OPTION%"=="quit" GOTO quit
IF /I "%OPTION%"=="b" GOTO menu
IF /I "%OPTION%"=="back" GOTO menu
ECHO.
ECHO ============INVALID INPUT============
ECHO Please select a number
ECHO or select 'Q' or 'B'.
ECHO ======PRESS ANY KEY TO CONTINUE======
PAUSE > NUL
GOTO Options
:Update
ECHO.
IF EXIST "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\Shortcut Browser *.bat" (
GOTO Update_1
) ELSE (
ECHO You have not installed the script yet. Please install the script first.
)
PAUSE
GOTO Options
:Update_1
IF EXIST "%tmp%\update.bat" (
2>NUL DEL "%tmp%\update.bat" || GOTO Options
)
SETLOCAL
FOR %%A IN (
"%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\Shortcut Browser *.bat"
) DO (
SET "old_version=%%~A"
SET "old_dir=%%~dpA"
SET "old_file=%%~nxA"
)
FOR %%A IN (
"%userprofile%\Desktop\Shortcut Browser *.bat"
) DO (
SET "new_version=%%~A"
SET "new_dir=%%~dpA"
SET "new_file=%%~nxA"
)
IF NOT DEFINED old_version (
ENDLOCAL
GOTO Options
) ELSE IF NOT DEFINED new_version (
ENDLOCAL
GOTO Options
)
(
ECHO #ECHO OFF
ECHO SETLOCAL
ECHO.
ECHO ECHO Update and restarting...
ECHO ^>NUL PING localhost -n 3
ECHO.
ECHO SET "old_version=%old_version%"
ECHO SET "new_version=%new_version%"
ECHO SET "updated_version=%old_dir%\%new_file%"
ECHO.
ECHO CALL :log /clear_log
ECHO.
ECHO IF NOT EXIST "%%new_version%%" (
ECHO CALL :log ERROR: Not exist "%%new_version%%".
ECHO EXIT /B 1
ECHO ^)
ECHO.
ECHO CALL :log Move old_version to old_version.bak.
ECHO MOVE "%%old_version%%" "%%old_version%%.bak" ^|^| (
ECHO CALL :log ERROR: Move failed to backup old version.
ECHO EXIT /B 2
ECHO ^)
ECHO.
ECHO CALL :log Copy new_version to old_version.
ECHO COPY "%%new_version%%" "%%appdata%%\Microsoft\Windows\Start Menu\Programs\Startup\" ^|^| (
ECHO CALL :log ERROR: Copy failed. Restore old version.
ECHO MOVE "%%old_version%%.bak" "%%old_version%%" ^|^| (
ECHO CALL :log ERROR: Restore old version failed.
ECHO EXIT /B 3
ECHO ^)
ECHO EXIT /B 4
ECHO ^)
ECHO.
ECHO CALL :log Delete old_version.bak.
ECHO DEL "%%old_version%%.bak" ^|^| (
ECHO CALL :log WARNING: Delete backup file failed.
ECHO ^)
ECHO.
ECHO IF NOT EXIST "%%updated_version%%" (
ECHO CALL :log ERROR: Not exist: "%%updated_version%%"
ECHO EXIT /B 5
ECHO ^)
ECHO.
ECHO ENDLOCAL
ECHO.
ECHO ECHO Ready to restart updated version
ECHO PAUSE
ECHO CALL "%old_dir%\%new_file%"
ECHO EXIT /B
ECHO.
ECHO :log
ECHO SETLOCAL
ECHO SET "log=%%tmp%%\update.log"
ECHO IF /I "%%~1"=="/clear_log" TYPE NUL ^> "%%log%%" ^& EXIT /B
ECHO IF /I "%%~1"=="/delete_log" 2^>NUL DEL "%%log%%" ^& EXIT /B
ECHO SET args=%%*
ECHO IF NOT DEFINED args EXIT /B
ECHO ECHO %%*
ECHO ^>^> "%%log%%" ECHO %%*
ECHO EXIT /B
) > "%tmp%\update.bat"
ENDLOCAL
START "Super Script 5000" "cmd /c "%tmp%\update.bat""
EXIT
:Quit
Tested on a Win7 VM. The script needs to restart on update else
weird issues may occur. CMD does not like scripts changing as it
is reading and interpreting them. Even reusing the same console
using START with /B may cause key input issues.
update.bat is overwritten every update as it stores absolute paths
so each update will be different paths with the filenames changing.
Using a wildcard with CALL may not work too well otherwise.
update.bat moves the old version to a .bak file, copies the new
version and if successful, deletes the .bak file, else moves the
.bak file to the old version. This is just to ensure a current
version always exists even if the update fails.
Changed quotes in :Options label from ' to ". Quotes are not
interchangeable like some other languages. Example: "%OPTION%"
will work if contains a space though '%OPTION%' may cause error.
I notice no SETLOCAL at the top of your full script. Advise you add
it unless you have a good reason not to.
I merged labels :Update_1 and :Update_2 into one.
Perhaps adjust Ping localhost -n number if more or less time is
needed.
Look at the %tmp%\update.log if a problem happens. Though expect
the errors to show in the console as the label :log in
update.bat echoes to console and writes to the log.

How do I make a batch log file?

How do I make a log file from this code. This has been answered a ton, but this file is huge and I want a simple log file. As you see I also tried to add a log file names RandomNamesLog.log. See if the output goes there.
I want all the code to be outputted into the log file, with error messages and confirm messages, like removing the #ECHO OFF value.
If you need more on what I want, please tell me.
#ECHO OFF
SETLOCAL EnableDelayedExpansion for /F "tokens=1,2 delims=#" %%a in
('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do ( set
"DEL=%%a" )
ECHO Random Names
ECHO Written By: Trevor T
ECHO UltimateGuidesPro.blogspot.com
ECHO.
ECHO.
REM Randomly renames every file in a directory.
SETLOCAL EnableExtensions EnableDelayedExpansion
REM 0 = Rename the file randomly.
REM 1 = Prepend the existing file name with randomly generated string.
SET PrependOnly=0
REM 1 = Undo changes according to the translation file.
REM This will only work if the file "__Translation.txt" is in the same
folder.
REM If you delete the translaction file, you will not be able to undo
the changes!
SET Undo=0
REM --------------------------------------------------------------------------
REM Do not modify anything below this line unless you know what you are doing.
REM --------------------------------------------------------------------------
SET TranslationFile=_TranslatonData.txt
SET LogFile=_RandomNamesLog.log
IF NOT {%Undo%}=={1} (
REM Rename files
ECHO You are about to randomly rename every file in the following folder:
ECHO %~dp0
ECHO.
ECHO A file named %TranslationFile% will be created which allows you to undo this.
ECHO Warning: If %TranslationFile% is lost/deleted, this action cannot be undone.
ECHO Type "OK" to continue.
SET /P Confirm=
IF /I NOT {!Confirm!}=={OK} (
ECHO.
ECHO Aborting.
GOTO :EOF
)
ECHO Original Name/Random Name > %TranslationFile%
ECHO ------------------------- >> %TranslationFile%
FOR /F "tokens=*" %%A IN ('DIR /A:-D /B') DO (
IF NOT %%A==%~nx0 (
IF NOT %%A==%TranslationFile% (
SET Use=%%~xA
IF {%PrependOnly%}=={1} SET Use=_%%A
SET NewName=!RANDOM!-!RANDOM!-!RANDOM!!Use!
ECHO %%A/!NewName!>> %TranslationFile%
RENAME "%%A" "!NewName!"
ECHO ----------------------------------------------------- >> %TranslationFile%
ECHO Designed by Trevor T | UltimateGuidesPro.blogspot.com >> %TranslationFile%
ECHO. >> %TranslationFile%
ECHO WARNING: THIS FILE REQUIRED TO UNDO RANDOM NAMING! THE FILE CAN BE MOVED AS LONG AS IT IS IN THE FOLDER WHEN USING THE UNDO RANDOM NAMES FUNCTION! >> %TranslationFile%
ECHO +---------+
ECHO | Credits |
ECHO +---------+
Echo.
ECHO Original Random Names script created by
call :colorEcho 0a "Jason Faulkner"
call :colorEcho 0a "HowToGeek.com"
ECHO ---------------------------------------
ECHO Script created by
call :colorEcho 0a "Trevor T"
ECHO -------------------------------------------
ECHO Color Text system created by
call :colorEcho 0a "Visual Magic, user on Stack Exchange"
ECHO Type "Exit" to quit
GOTO :Exit
:Exit
SET /P Confirm=
IF /I NOT {!Confirm!}=={Exit} (
ECHO.
ECHO Please try again
GOTO :Exit2
Exit
:Exit2
SET /P Confirm=
IF /I NOT {!Confirm!}=={OK} (
ECHO.
ECHO Please try again
GOTO :Exit
)
)
)
) ELSE (
ECHO UNDO MODE
IF NOT EXIST %TranslationFile% (
ECHO Missing translation file: %TranslationFile%
ECHO Please make sure %TranslationFile% is in the location of the random files. Otherwise it will give this error.
PAUSE
GOTO :EOF
)
ECHO Undoing...
FOR /F "skip=2 tokens=1,2 delims=/" %%A IN (%TranslationFile%) DO RENAME "%%B" "%%A"
DEL /F /Q %TranslationFile%
ECHO Completed Undo!
Pause
)
Exit
REM This is the color text code. Don't touch this, unless you know a better way to use color text.
:colorEcho
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1i
I have rewritten your script fixing all of the problems I could see and removing the pointless code to add colored text.
Test it to see if it works as it should adding whatever you think I've missed.
#ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
ECHO Random Names
ECHO Written By: Trevor T
ECHO UltimateGuidesPro.blogspot.com
ECHO.
REM Randomly renames every file in a directory.
REM 0 = Rename the file randomly.
REM 1 = Prepend the existing file name with randomly generated string.
SET "PrependOnly=0"
REM 1 = Undo changes according to the translation file.
REM This will only work if the file "_TranslationData.txt" is in the same folder.
REM If you delete the translaction file, you will not be able to undo the changes!
SET "Undo=0"
REM --------------------------------------------------------------------------
REM Do not modify anything below this line unless you know what you are doing.
REM --------------------------------------------------------------------------
SET "TranslationFile=_TranslationData.txt"
IF "%Undo%"=="1" GOTO UNDOIT
ECHO You are about to randomly rename every file in the following folder:
ECHO %CD%
ECHO.
CHOICE /M "Do you want to continue "
IF NOT %ERRORLEVEL%==1 (
ECHO.
ECHO Aborting.
TIMEOUT -1
GOTO :EOF
)
ECHO A file named %TranslationFile% will be created which allows you to undo this.
ECHO Warning: If %TranslationFile% is lost/deleted, this action cannot be undone.
(
ECHO ;Original Name/Random Name
ECHO ;-------------------------
FOR %%A IN (*) DO IF NOT "%%A"=="%~nx0" IF NOT "%%A"=="%TranslationFile%" (
SET "Use=%%~xA"
IF "%PrependOnly%"=="1" SET "Use=_%%A"
SET "NewName=!RANDOM!-!RANDOM!-!RANDOM!!Use!"
ECHO %%A/!NewName!
REN "%%A" "!NewName!"
)
ECHO ;-----------------------------------------------------
ECHO ;Designed by Trevor T ^| UltimateGuidesPro.blogspot.com
ECHO.
ECHO ;WARNING: THIS FILE REQUIRED TO UNDO RANDOM NAMING!
ECHO ; THE FILE CAN BE MOVED AS LONG AS IT IS IN THE FOLDER WHEN USING THE UNDO RANDOM NAMES FUNCTION!
)>"%TranslationFile%"
ECHO +---------+
ECHO ^| Credits ^|
ECHO +---------+
ECHO.
ECHO Original Random Names script created by Jason Faulkner # HowToGeek.com
ECHO -------------------------------------------
ECHO Script created by Trevor T
ECHO -------------------------------------------
TIMEOUT -1
GOTO :EOF
:UNDOIT
ECHO UNDO MODE
IF NOT EXIST "%TranslationFile%" (
ECHO Missing translation file: %TranslationFile%
ECHO Please make sure %TranslationFile% is in the location of the random files. Otherwise it will give this error.
TIMEOUT -1
GOTO :EOF
)
ECHO Undoing...
FOR /F "USEBACKQ TOKENS=1-2 DELIMS=/" %%A IN ("%TranslationFile%") DO REN "%%B" "%%A"
DEL /F "%TranslationFile%"
ECHO Completed Undo!
TIMEOUT -1
GOTO :EOF
Once you are happy with it edit your opening question explaining what it is you want to have in the log file and how you need it to look.
I use this. it seems to work.
It just starts a log file and maintains logs.
You can set logpath and logname (base name) then you call this create_logfile
It creates a semi-random log file.
Now you write to the set logfile
I'm not an advanced coder. Please feel free to correct:
#echo off
rem
echo %date% %TIME%
rem Log File Path
if "%logpath%" == "" set logpath=%~dp0
if "%logpath:~-1%" == "\" set logpath=%logpath:~0,-1%
rem Make log file name
if "%logname%" == "" set logname=log
set t=%TIME: =0%
set d=%DATE%
set logfilename=%logname%_%d:~12,2%%d:~4,2%%d:~7,2%%t:~0,2%%t:~3,2%%t:~6,2%.log
set t=
set d=
rem Test
echo full log file name = %logfilename%
echo find base log name = %logfilename:~0,-17%
echo log path = %logpath%
rem Logs to maintain
set /a dellog=5
rem Find file to delete
set var=
set /a cnt=0
set fltodel=
set fstfle=
for %%a in (%logpath%\%logname%*.log) do (
set var=%%a
call set /a "cnt+=1"
echo %%cnt%%| findstr /l "1" >nul && (call set fstfle=%%var%%)
echo %%cnt%%| findstr /l "%dellog%" >nul && (call set fltodel=%%fstfle%%)
)
rem Delete old log
echo file to delete %fltodel%
if exist %fltodel% (del /q %fltodel%) else (echo "%fltodel%" does not exist. nothing to delete.)
echo tryed to delete
rem Create Log File and logfile attribute
set logfile=%logpath%\%logfilename%
if exist %logfile% (
echo start logging... "%~0" on %date% %time% >> %logfile%
) ELSE (
echo Start Log for "%~0" on %date% %time% > %logfile%
)

Batch IF doesn't work

I made a simple BATCH file for notes, it just deletes a folder, makes a new one, and puts in a file called note.txt and then edits it... for some reason, it doesn't do ANYTHING at all! not even removing the folder, here's the code:
goto start
:abort
ECHO Aborted!
PAUSE
GOTO start
:replace
del /q "D:\Users\Eldar\Desktop\Note Folder"
mkdir "Note Folder"
#echo>"D:\Users\Eldar\Desktop\Note Folder\note.txt"
#echo %note%> "D:\Users\Eldar\Desktop\Note Folder\note.txt"
pause
:start
#ECHO OFF
color e
cls
echo Put the note in here:
set /p LastNote=<"D:\Users\Eldar\Desktop\Note Folder\note.txt"
SET /P note=
cls
echo Note has been saved!
echo also, the last note you saved was: "%LastNote%".
echo so are you sure you want to replace this note with a new one (Y/N)?
SET /P agree=
IF "%agree%"=="y" (
ECHO goto replace
) ELSE (
GOTO abort
)
There are few errors in your script:
del can delete only empty folders. Use rmdir /s /q folder_name to remove folder with files
Remove ECHO in ECHO goto replace
You are using full paths everywhere except mkdir. Is it correct?
My working version:
#echo off
goto start
:abort
echo Aborted!
pause
goto start
:replace
rmdir /s /q ".\TestF"
mkdir "TestF"
echo>".\TestF\note.txt"
echo %note%> ".\TestF\note.txt"
pause
:start
color e
cls
echo Put the note in here:
set /p LastNote=<".\TestF\note.txt"
set /p note=
cls
echo Note has been saved!
echo also, the last note you saved was: "%LastNote%".
echo so are you sure you want to replace this note with a new one (Y/N)?
set /p agree=
if "%agree%"=="y" (
goto replace
) else (
goto abort
)
There appears to be no reason to remove the Note Folder directory or even to delete the note.txt file.
How does it perform if you rewrite it like this?
#Echo Off
Color 0E
Set "LastNote="
If Exist "%UserProfile%\Desktop\Note Folder\note.txt" (
Set/P LastNote=<"%UserProfile%\Desktop\Note Folder\note.txt"
)
If Not Defined LastNote GoTo replace
:ask
ClS
Echo=The last note you saved was:
Echo=%LastNote%
Echo=
Choice /M "Would you like to replace this note with a new one"
If "%ErrorLevel%"=="1" GoTo replace
Echo=
Echo=Aborted!
Timeout -1
GoTo ask
:replace
ClS
Set/P "note=Put the note in here: "
If "%note%"=="" GoTo ask
Echo=Note has been saved!
If Not Exist "%UserProfile%\Desktop\Note Folder\" (
MD "%UserProfile%\Desktop\Note Folder"
)
(Echo=%note%)>"%UserProfile%\Desktop\Note Folder\note.txt"
Timeout -1
GoTo ask
For the benefit of the OP, here is your version of your script with the major flaws removed and with unnecessary lines kept in.
#goto start
:abort
ECHO Aborted!
PAUSE
GOTO start
:replace
rmdir "D:\Users\Eldar\Desktop\Note Folder"
mkdir "D:\Users\Eldar\Desktop\Note Folder"
echo.>"D:\Users\Eldar\Desktop\Note Folder\note.txt"
>"D:\Users\Eldar\Desktop\Note Folder\note.txt" echo %note%
pause
:start
#ECHO OFF
color e
cls
echo Put the note in here:
set /p LastNote=<"D:\Users\Eldar\Desktop\Note Folder\note.txt"
SET /P note=
cls
echo Note has been saved!
echo also, the last note you saved was: "%LastNote%".
echo so are you sure you want to replace this note with a new one (Y/N)?
SET /P agree=
IF "%agree%"=="y" (
goto replace
) ELSE (
GOTO abort
)

Making a batch file do something once

I'm making a game and I want a personalized username option that only appears once.
Here is an example:
#echo off
:onetime
echo please enter a username
echo.
set /p newuser=%newuser%:
echo %newuser%> cfg.txt
goto menu
:menu
for /f "tokens=* delims=" %%x in (cfg.txt) do echo %%x
cls
...
I'm trying to figure out how to make :onetime happen once, so that it sends the username to cfg.txt
Anyone know how?
I have cleaned up your code and provided a completed working script, and noted where you will put your game code.
Although Delayed expansion is not needed for this code, I have placed it in the script as you had it in your original script.
Please be mindful of the variable names I have chosen as they are used in several locations.
I have tried to comment the code with info on what it is doing, and I would be happen to explain further if needed.
I'd like to actually play your game when you are completed with it, if I may. :)
Hope that helps.
Ben
BPG.cmd
REM Script: BPG.cmd
REM Version: 1.0
REM Description: Game to play about Monsters.
Rem Notes: Currently Implementing Menu System.
Rem Sets up Variables and checks if the script needs to be re-called.
#(
SETLOCAL ENABLEDelayedExpansion
echo off
SET "eLvl=0"
SET "ScriptFolder=%~dp0"
SET "Log=%~dpn0.log"
SET "ConfigFile=%~dpn0_cfg.txt"
IF /I "%~1" NEQ "MAX" (
ENDLOCAL
ECHO.Game not started Maximized, Opening in a New Window by Running: Start "BPG 1 A Batch of Monsters" /MAX "%~dpnx0" MAX
Start "BPG 1 A Batch of Monsters" /MAX "%~dpnx0" MAX
EXIT /b %eLvl%
)
COLOR 2
)
REM Calls Main Function.
CALL :Main
REM Ends the script.
(
ENDLOCAL
EXIT /b %eLvl%
)
REM Main Function, most of your coding goes here, and this function calls sub functions.
:Main
Rem Check if Config file exists, if it does not, then call the New User Function.
IF NOT EXIST "%ConfigFile%" (
CALL :NewUser
)
Rem Load Username from Config file.
FOR /F "Tokens=*" %%A IN ('Type "%ConfigFile%"') DO (
SET "_UserName=%%~A"
)
Rem Call Menu System
CALL :Menu
REM Based off the option chosen Either Start a new Game or Skip to the End.
REM ECHO.CALL %_Menu_Choice%
CALL %_Menu_Choice%
GOTO :EOF
:NewUser
SETLOCAL
REM Get the Username Input
SET /P "_User=Please Enter a Username: "
REM Output the Username to the config file, overwriting all the file contents:
echo.%_User%>"%ConfigFile%"
ENDLOCAL
GOTO :EOF
:Menu
SETLOCAL
REM Output the Config file contents:
Type "%ConfigFile%"
REM Clear the screen
cls
echo ______ _______ _______
echo I ___ \ I ____ I I ____ \
echo I I I II I II I I \/
echo I I__/ / I I____II I I
echo I __ I I _____I I I ____
echo I I \ \ I I I I \_ I
echo I I___I II I I I___I I
echo I______/ I_/ I_______I A BATCH OF MONSTERS
echo.
echo.
echo 1) Begin
echo.
echo 2) Exit
echo.
set /p "_Choice=%_UserName%, Enter a Number: "
(
REM End the local variable Space, and Set return variables based on the choice, or re-draw the menu.
ENDLOCAL
IF /I "%_Choice%" EQU "1" (
REM ECHO.%_Choice% EQU 1
SET "_Menu_Choice=:Begin_Game"
) ELSE (
IF /I "%_Choice%" EQU "2" (
REM ECHO.%_Choice% EQU 2
SET "_Menu_Choice=GOTO :EOF"
) ELSE (
ECHO.%_Choice% Not Valid!
PAUSE
GOTO :Menu
)
)
)
goto :EOF
:Begin_Game
REM All the remaining code for your game should probably go here.
GOTO :EOF
try checking file existence :
#echo off
:onetime
setlocal enableDelayedExpansion
if not exist "cfg.txt" (
echo please enter a username
echo.
set /p newuser=%newuser%:
echo !newuser!> cfg.txt
goto menu
)
:menu
for /f "tokens=* delims=" %%x in (cfg.txt) do echo %%x
cls

How to do while loop in windows batch

I wrote a windows batch script to check and move files to another directory based on the list I put in a notepad file named list.txt. But I have no idea that how to set the while-loop. Only to jump out of the subroute when the condition fulfill.
In C Programming, we could write like this by setting a while-loop direcly. But seems in windows batch is quite different.
All I want is like this:
Directory A:
1. A.txt
2. B.txt
3. list.txt (By line sequential with filename want to move)
4. process.bat
Directory B:
None of files (Then move a file by order of line set in list.txt) OR
A.txt (If already existed a text file in directory, process.bat will pause before A.txt disappear)
Process.bat
#echo off
:readline
for /f "tokens=*" %%a in (list.txt) do call :processline %%a
goto :eof
:processline
if exist D:\DirectoryA\*.txt (
echo %time% >> D:\AutoLog\Log.txt
echo Previous job did not finished yet. >> D:\AutoLog\Log.txt
Timeout /t 30
echo.
)
set name=%*
if exist %name%.txt (
echo %time% >> D:\AutoLog\Log.txt
echo File found and processing %name%.txt now... >> D:\AutoLog\Log.txt
copy "%~dp0\%name%.txt" "D:\DirectoryB"
echo Transfer %name%.txt completed!! >> D:\AutoLog\Log.txt
echo. >> D:\AutoLog\Log.txt
Timeout /t 790
echo.
echo ==============================================================
)
:eof
Please guide me to finish the script by using a while-loop method. Thanks
I change some script sequence and it works now.
#echo off
:readline
for /f "tokens=*" %%a in (list.txt) do call :processline %%a
goto :eof
:processline
set name=%*
if exist C:\Test2\*.txt (
echo %date% %time% >> C:\Test2\Log.txt
echo Previous job did not finished yet. >> C:\Test2\Log.txt
Timeout /t 5
echo.
echo. >> C:\Test2\Log.txt
goto :processline
)
if exist %name%.txt (
echo %date% %time% >> C:\Test2\Log.txt
echo File found and processing %name%.txt now... >> C:\Test2\Log.txt
copy "%~dp0\%name%.txt" "C:\Test2"
echo Transfer %name%.txt completed!! >> C:\Test2\Log.txt
echo. >> C:\Test2\Log.txt
Timeout /t 10
echo.
echo ==============================================================
)
:eof
This will copy as well as count the number of lines from your text file..
# echo off
:TextPath
cls
set /p Input=#1 Enter the full path of the text file :
set /p Source=#2 Enter the full path of Source :
set /p Target=#3 Enter the full path of Destination :
:choice
set /P c=Ready to Continue[Y/N]?
if /I "%c%" EQU "Y" goto :Yes
if /I "%c%" EQU "N" goto :No
goto :choice
:Yes_Local
for /f "delims=" %%i in (%Input%) do echo f| xcopy /f /y "%Source%\%%i" "%Target%\%%i"
for /f %%C in ('Find /V /C "" ^< %Input%') do set Count=%%C
msg * No of Lines executed= %Count%
exit
:No
cls
color e
echo Redirecting to Main....
PING 127.0.0.1 -n 2 >NUL
cls
echo Please wait
PING 127.0.0.1 -n 4 >NUL
goto TextPath

Resources