批处理命令冲突

3
我编写了一个批处理脚本,允许用户输入网站的URL和时间(以分钟为单位),然后将该URL添加到hosts文件中,并在时间到期后将其删除。(有效阻止网站一段时间)
当它首次运行时,它通过创建另一个批处理文件来从hosts文件中删除该网站,并使用AT命令在指定时间启动新的批处理文件。它可以用于阻止多个网站,唯一的问题是如果有多个网站同时解锁,那么每个新创建的批处理文件的解锁过程似乎会发生冲突。如您所见,我尝试通过延迟批处理文件的运行来解决此问题,直到其他批处理文件完成。不幸的是,它大多数时候都不起作用。有时如果时间很合适,两个批处理文件都会在没有相互干扰的情况下执行。以下是代码,请原谅我的可怕编码技术,可能难以理解:
@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

该程序必须以管理员身份运行才能正常工作。因此,我将其编译为.exe文件并添加了管理员清单。虽然将其编译为.exe文件不是问题,但当我运行批处理或已编译的.exe文件时仍有相同的问题。


3
最史诗级的批处理脚本,点赞+1! - Kornel Kisielewicz
你为什么不使用PowerShell呢? - manojlds
1
@manojlds,有成千上万更强大的替代方案,但编写批处理脚本就像是一种古老的艺术,人们练习它并不是因为它是最快的方式,而是因为它的仪式感...就像茶道一样... - Kornel Kisielewicz
@Kornel Kisielewicz 哈哈,太对了 :P - Josh
1
此外,我认为这个答案会为您提供一种更简单的方法来删除特定行的文本:https://dev59.com/j3RC5IYBdhLWcg3wD87r - Gary
显示剩余4条评论
3个回答

1

我对此有点好玩...既然你还没有标记任何答案,我想你可能想看看它。看起来你的主要问题是你想能够阻止多个网站并同时解除阻止,对吗?

使用你的方法,我用一个动态循环批处理进行了修改,允许你添加尽可能多的网站以暂时禁止访问。这样一来,每次只有一个批处理正在访问hosts文件。在删除自身之前,它还会清理所有创建的内容。希望这可以帮到你:

@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

另外...我使用了schtasks而不是AT,这样我可以轻松地找到任务并删除它,因为它允许您应用唯一的名称,而不是从分配的ID号码开始。


0

我对你脚本中广泛使用的IF语句有些疑问:

if %mm% gtr 60...

如果想要检查大于60分钟的想法,我猜这可能是你遇到问题的原因。分钟值可以是0到59,而不是60。

我不认为那是问题,因为如果%mm%等于60,那么小时会增加一小时,分钟会归零。计算运行新批处理文件之前需要等待的时间似乎工作正常。唯一的问题似乎是如果同时有多个网站被解除封锁。 - Josh
抱歉,我仔细阅读了代码的那一部分 - 你是对的。只是出于好奇,TIMEOUT 真的在等待吗?你能否将 %TIME% 的值(timeout 语句之前和之后)输出到一个 TEMP 文件中,以查看 TIMEOUT 是否绕过了等待? - Arun
@Josh,%mm%怎么可能超过59呢?它不是从hh:mm:ss.ms中读取mm吗? - barlop
@barlop 因为假设现在是6:30,用户输入了30分钟,那么时间就会变成6:60...所以如果发生这种情况,程序必须将小时增加1并将分钟重置为0。 - Josh
@barlop 如果您查看开头,他有一个用户输入为%mins%,因此在:SET中进行数学运算时,分钟可以增加超过60。 - Anthony Miller

0

我不认为这会解决问题,但如果您没有创建第二个文件,而是使用原始文件并使用参数指示删除,可能会使其更易于阅读/管理。

例如(未经测试,仅供参考):

@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%

你用什么工具来将它编译成.EXE文件呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接