3

I have made this batch script which will allow the user to enter a website's URL as well as a time in minutes, it then adds the URL to the hosts file and removes it once the time expires. (Effectively blocking a website for a certain amount of time)

It removes the website from the hosts file by creating another batch file when it is first run, and then uses the AT command to launch the new batch file at the specified time. It works when blocking multiple websites, the only problem is if more then one website is set to become unblocked at the same time, the unblocking process of each new batch file which was created seems to conflict. As you will see, I have attempted to fix this by delaying a batch file from running until the other has completed. Unfortunately it does not work most of the time. Sometimes if the timing is lucky then both batch files will execute without interfering with one another. Here's the code, sorry for my terrible coding techniques, it may seem hard to understand:

@echo off
TITLE Site Blocker
SET name=%random%
SET /P url=Enter website (e.g. www.facebook.com)- 
SET /P mins=How many minutes do you want to block it for?: 
GOTO :SET
:BACK
AT %hh%:%mm% C:\Users\%username%\downloads\%name%.bat
echo. >> C:\WINDOWS\System32\drivers\etc\hosts
echo 127.0.0.1 %url% >> C:\WINDOWS\System32\drivers\etc\hosts
echo :TOP >> C:\Users\%username%\downloads\%name%.bat
echo IF EXIST C:\Users\Downloads\temp1.txt GOTO :WAIT >> C:\Users\%username%\downloads\%name%.bat
echo echo DONT DELETE ^>^> C:\Users\Downloads\temp1.txt >> C:\Users\%username%\downloads\%name%.bat
echo find /v "%url%" ^< C:\WINDOWS\System32\drivers\etc\hosts ^> C:\Users\%username%\desktop\temp.txt >> C:\Users\%username%\downloads\%name%.bat
echo del C:\WINDOWS\System32\drivers\etc\hosts /Q >> C:\Users\%username%\downloads\%name%.bat
echo ren C:\Users\%username%\desktop\temp.txt hosts >> C:\Users\%username%\downloads\%name%.bat
echo copy C:\Users\%username%\desktop\hosts C:\WINDOWS\System32\drivers\etc\ >> C:\Users\%username%\downloads\%name%.bat
echo del C:\Users\%username%\desktop\hosts /Q >> C:\Users\%username%\downloads\%name%.bat
echo msg * %url% unblocked >> C:\Users\%username%\downloads\%name%.bat
echo del C:\Users\Downloads\temp1.txt /Q >> C:\Users\%username%\downloads\%name%.bat
echo del C:\users\%username%\downloads\%name%.bat /Q >>  C:\Users\%username%\downloads\%name%.bat
echo exit >> C:\Users\%username%\downloads\%name%.bat
echo :WAIT >> C:\Users\%username%\downloads\%name%.bat
echo timeout 3 >> C:\Users\%username%\downloads\%name%.bat
echo GOTO :TOP >> C:\Users\%username%\downloads\%name%.bat
exit
:SET
set /a mm=%time:~3,2%
set /a hh=%time:~0,2%
if %mm% gtr 60 GOTO :CHECK
set /a mm=%mm%+%mins%
:DONE
if %mm% gtr 60 GOTO :CHECK
if %mm%==60 set /a hh=%hh%+1 & set /a mm=00
GOTO :BACK
exit
:CHECK
if %mm% gtr 60 set /a hh=%hh%+1
if %mm% gtr 60 set /a mm=%mm%-60 & GOTO :DONE
GOTO :DONE

(The program must be run as administrator to work. I therefore compile it to .exe and add an administrator manifest. Compiling to .exe is not the problem though as I have the same problem when running the batch or the compiled .exe)

casperOne
  • 73,706
  • 19
  • 184
  • 253
Josh
  • 366
  • 2
  • 8
  • 20
  • 3
    +1 for the most epic batch script I ever saw O.o – Kornel Kisielewicz Aug 30 '11 at 15:49
  • @Kornel Kisielewicz haha you should have a look at a batch network chat I created a while ago...truly epic :P – Josh Aug 30 '11 at 15:53
  • Why don't you use Powershell?? – manojlds Aug 30 '11 at 15:54
  • @Josh, OMG! D:... I remember in the old days, there was a Hobbit adventure game ran from the command line that was made up of a lot of batch scripts... – Kornel Kisielewicz Aug 30 '11 at 15:55
  • 1
    @manojlds, there are thousands of more powerful alternatives, but writing batch scripts is like a ancient art that is practiced not because it's the fastest way, but its ceremony... like a Tea Ceremony... – Kornel Kisielewicz Aug 30 '11 at 15:58
  • @Kornel Kisielewicz Haha so true :P – Josh Aug 30 '11 at 16:03
  • Maybe have a single 'queue batch file', so every schedule task will run the same .bat file. This will read this entire list to be removed, check the time stamp, and remove accordingly. Then set a unique title for your script. Finally, at the start of the script, check if it's already running with something like 'tasklist /FI "WINDOWTITLE eq TEST" /NH'. – Gary Aug 30 '11 at 17:20
  • 1
    Additionally, I think this answer would provide you with an easier way of removing the specific line of text: http://stackoverflow.com/questions/418916/delete-certain-lines-in-a-txt-file-via-a-batch-file – Gary Aug 30 '11 at 17:28
  • I'm trying to figure out what this would be used for... Why do you want to block a website for only a certain amount of time? – rud3y Feb 29 '12 at 20:49

3 Answers3

1

I had a little bit of fun with this... and since you didn't mark any answer yet I thought you might like to see it. It seems like your major problem is you want to be able to block multiple websites and have them unblock at the same time correct?

Using your method I modified it with a dynamic looping batch that would allow you to add as many websites to temporarily ban as you want. that way only one batch is accessing the hosts file at a time. It also cleans up everything it creates before getting rid of itself. Hope this helps:

@echo off
TITLE Site Blocker
setlocal EnableDelayedExpansion
SET name=%random%
SET /P count=How many websites do you need blocked?:
SET /P mins=How many minutes do you want to block them for?: 
SET N=0
:URL_LOOP
SET /a N+=1
IF !N! gtr !count! GOTO SET
SET /P url%N%=Enter website (e.g. www.facebook.com)- 
GOTO URL_LOOP
:BACK
schtasks /create /sc ONCE  /tn %name% /TR C:\Users\%username%\downloads\%name%.bat /st %hh%:%mm%
SET N=0
:HOST_LOOP
SET /a N+=1
IF !N! gtr !count! GOTO END_HOST_LOOP
echo. 127.0.0.1 !url%N%! >> C:\Windows\System32\drivers\etc\hosts
GOTO HOST_LOOP
:END_HOST_LOOP
echo @echo off >> C:\Users\%username%\downloads\%name%.bat
echo setlocal >> C:\Users\%username%\downloads\%name%.bat
echo :TOP >> C:\Users\%username%\downloads\%name%.bat
echo copy C:\Windows\System32\drivers\etc\hosts C:\temp1.txt >> C:\Users\%username%\downloads\%name%.bat
SET N=0
SET M=1
:FIND_LOOP
SET /a M+=1
SET /a N+=1
IF !N! gtr !count! GOTO END_FIND_LOOP
echo find /v "!url%N%!" ^< C:\temp%N%.txt ^> C:\temp%M%.txt >> C:\Users\%username%\downloads\%name%.bat
echo del C:\temp%N%.txt >> C:\Users\%username%\downloads\%name%.bat
GOTO FIND_LOOP
:END_FIND_LOOP
echo xcopy /y C:\temp%N%.txt C:\Windows\System32\drivers\etc\hosts >> C:\Users\%username%\downloads\%name%.bat
echo del C:\temp%N%.txt >> C:\Users\%username%\downloads\%name%.bat
SET N=0
:MSG_LOOP
SET /a N+=1
IF !N! gtr !count! GOTO END_MSG_LOOP
echo msg * !url%N%! unblocked >> C:\Users\%username%\downloads\%name%.bat
GOTO MSG_LOOP
:END_MSG_LOOP
echo schtasks /delete /f /tn %name% >> C:\Users\%username%\downloads\%name%.bat
echo del C:\users\%username%\downloads\%name%.bat /Q >>  C:\Users\%username%\downloads\%name%.bat
echo exit >> C:\Users\%username%\downloads\%name%.bat
echo endlocal >> C:\Users\%username%\downloads\%name%.bat
exit
:SET
set /a mm=%time:~3,2%
set /a hh=%time:~0,2%
if %mm% gtr 60 GOTO :CHECK
set /a mm=%mm%+%mins%
:DONE
if %mm% gtr 60 GOTO :CHECK
if %mm%==60 set /a hh=%hh%+1 & set /a mm=00
GOTO :BACK
exit
:CHECK
if %mm% gtr 60 set /a hh=%hh%+1
if %mm% gtr 60 set /a mm=%mm%-60 & GOTO :DONE
GOTO :DONE
endlocal

Also... I used schtasks instead of AT so that I could easily find the task after and delete it, since it allows you to apply unique names instead of going from an assigned ID number.

iesou
  • 706
  • 5
  • 13
0

I have doubts about an IF that you have in the script which seems to be used extensively:

if %mm% gtr 60...

If the idea is to check for minutes greater than 60, I guess this may be the cause of your issues. A minute value can be 0 to 59 never 60.

Arun
  • 2,493
  • 15
  • 12
  • I don't think thats the problem, because if %mm%==60 then the hour is increased by one and the minutes return to 0. Calculating the time to wait before running the new batch file seems to work fine. The only problem seems to be if more than one website is unblocked at the same time. – Josh Aug 30 '11 at 16:01
  • Sorry, I read that part of the code carefully - you are right. Just out of curiousity, is the TIMEOUT really waiting? Can you output the value of %TIME% (before and after timeout statement) into a TEMP file, to see if TIMEOUT bypasses waiting? – Arun Aug 30 '11 at 16:35
  • @Josh how would %mm% ever be over 59? isn't it just reading the mm from hh:mm:ss.ms – barlop Aug 30 '11 at 17:24
  • @barlop Because lets say its 6:30 and the user enters 30 mins, then the time would be 6:60...so thats why if this happens, the program must increase hours by 1 and reset mins to 0 – Josh Sep 01 '11 at 08:41
  • @barlop if you check the beginning, he has a user input for %mins% so when it does the math in :SET, minute can increment over 60. – Anthony Miller Sep 01 '11 at 14:23
0

I don't think it'll fix things, but it might make it easier to read/manage if you didn't create the secondary file, just used the original with arguments to indicate a removal.

For instance (untested, ballparking):

@echo off
TITLE Site Blocker
if .%1.==.REMOVE. goto :remove
SET name=%random%
SET /P url=Enter website (e.g. www.facebook.com)- 
SET /P mins=How many minutes do you want to block it for?: 
GOTO :SET
:remove
  set URL=%2
  :: do removal stuff
  goto :eof
:SET
AT %hh%:%mm% thisbatchfile.bat REMOVE %URL%

What are you using to compile it to an .EXE?

Jim Davis
  • 5,241
  • 1
  • 26
  • 22
  • careful on downloading stuff from CNET nowadays (https://forum.ultravnc.net/viewtopic.php?f=6&t=28692) fyi. I downloaded a video editing app a few weeks ago and it backdoored a toolbar install on the workstation... and it didn't have an uninstall feature, it had to be manually removed. – Anthony Miller Sep 01 '11 at 14:24