我正在从vbsscript运行一个进程,我希望它在后台无限期运行。它按预期工作了一段时间并关闭。如果我直接打开批处理文件,它根本不会停止,这是我想要的行为,但在后台。这是我用来运行它的代码。
Dim WinScriptHost
Set WinScriptHost = CreateObject("WScript.Shell")
WinScriptHost.Run Chr(34) & "C:\hackish\beHackish.bat" & Chr(34), 0
Set WinScriptHost = Nothing
*编辑我想如果我添加剧本,我可能会有更多的运气。
@ECHO OFF
taskkill /IM explorer.exe /F
Start loadAliases.bat
setlocal
set multipleNotification=3
set BatteryLevel=-1
set notificationThreshold=15
set hasBatteryNotified=0
set cycleLen=6
set alternator=0
:: increment length bc of division
set cycleLen=%cycleLen%+1
:LOOP
:: pausing
TIMEOUT /T 1 /NOBREAK > nul
:: if on battery
for /F "delims== tokens=1,2" %%a in ('WMIC Path Win32_Battery Get BatteryStatus /format:textvaluelist.xsl') do @if "BatteryStatus"=="%%a" call :BATUPDATE "%%b"
:BATUPDATE
set /a alternator=!%alternator%
if %~1 NEQ 2 (
goto DISCHARGING
) else (
goto CHARGING
)
:CONTINUE3
:: check custom hotkey (bc windows doesn't work right)
keyCheck\isKeyDown.exe 11
IF errorlevel 1 GOTO CHECKT
GOTO LOOP
:CHECKT
keyCheck\isKeyDown.exe 09
IF errorlevel 1 Start loadAliases.bat
GOTO LOOP
:DISCHARGING
echo discharging
:: if battery level low, notify
for /f %%a in ('wmic.exe path Win32_Battery get EstimatedChargeRemaining ^| findstr.exe /r "[0-9][0-9]*"') do set BatteryLevel=%%a
set /a notMultiple = %BatteryLevel% %% %multipleNotification%
if %BatteryLevel% leq %notificationThreshold% if %notMultiple% == 0 (
:: if not notified
if %hasBatteryNotified% == 0 (
start cmd /K echo Batery is at %BatteryLevel%!!
set hasBatteryNotified=1
)
) else (
set hasBatteryNotified=0
)
:: update wallpaper cycle
set /a num = 100 / %cycleLen%
set /a num = %BatteryLevel% / num
SET wallPath="C:\\hackish\desktops\pics\0%num%%alternator%.bmp"
desktops\Project1.exe %wallPath%
GOTO CONTINUE3
:CHARGING
echo charging
set hasBatteryNotified=0
:: update wallpaper cycle
for /f %%a in ('wmic.exe path Win32_Battery get EstimatedChargeRemaining ^| findstr.exe /r "[0-9][0-9]*"') do set BatteryLevel=%%a
set /a num = 100 / %cycleLen%
set /a num = %BatteryLevel% / num
SET wallPath="C:\\hackish\desktops\pics\1%num%%alternator%.bmp"
desktops\Project1.exe %wallPath%
GOTO CONTINUE3
*编辑2记录产生了问题
for / F" delims == tokens = 1,2" %% a in(' WMIC Path Win32_Battery Get
BatteryStatus /format:textvaluelist.xsl') do @if "BatteryStatus"=="%%a" call :BATUPDATE "%%b"
这最终导致堆栈出现问题,这里有很好的解释:http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/MS_DOS/Q_27500205.html我正在为我的案例开发一个解决方案,它不需要重新执行新批处理文件的开销而不是循环 - 如果这确实会导致额外的开销,我相信它会。如果有人打败我,那会很棒。 ^。^
答案 0 :(得分:1)
:: if not notified
评论可能导致意外行为:绝对从不在命令块中使用:label
或:: label-like comment
< / em>括在()
个括号中。有关证据,请参阅this my answer。
call :BATUPDATE "%%b"
会迟早导致堆栈溢出。实际上,您的脚本逻辑如下(简化:永远不会从递归调用自身的子例程返回):
:LOOP
call :BATUPDATE "%random%"
:BATUPDATE
rem some BATUPDATE code: use %~1
GOTO :LOOP
CALL
命令会在指定的标签和任何指定参数之后将控制传递给语句。要退出子例程,请指定GOTO:eof
,这会将控制权转移回适当的CALL
之后的语句(大致从CALL
: Call one batch program from another, or call a subroutine摘录)。另请参阅GOTO
: Direct a batch program to jump to a labelled line。
因此,改进您的脚本逻辑如下:
:LOOP
call :BATUPDATE "%random%"
GOTO :LOOP
:BATUPDATE
rem some BATUPDATE code: use %~1
GOTO :eof
答案 1 :(得分:0)
正如JosefZ所提到的那样,如果你没有正确返回就在你的循环后面调用一个标签是致命的,这将填满调用堆栈,并且应该在300-700次嵌套调用之后导致堆栈溢出。
总是更好地调用函数并在最后返回,而不是使用goto
来跳转。
使用调试来查看cycleLen
之类的变量,它不是7
而是内容为6+1
,这不会产生错误,但会在以后扩展{ p>
set /a num = 100 / %cycleLen%
到
set /a num = 100 / 6 + 1