2016-01-03 2 views
0

Я создал файл сценария партии, чтобы обнаружить возникновение определенного события. Тогда я побежал, что пакетный файл в качестве фонового процесса, используя следующий код, сохраняются в файле .vbs:Бесконечный пакетный скрипт останавливается через некоторое время

CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False 

Я не знаю, почему через 1 - 2 часа процесс этой работы исчезнет, ​​или я не» я знаю, почему эта работа не работает непрерывно, без каких-либо перерывов, как ее планировали и планировали делать.

Может ли кто-нибудь сказать мне, почему? И как решить эту проблему? Я имею в виду, как заставить мой скрытый командный файл работать в течение неограниченного периода времени?

Это пакетный файл

@ECHO OFF 
set count=0 
:LOOP 
REM To Check the battery status, providing that 1 is discharging 
REM and 2 is connected to the AC 
for /F "delims== tokens=1,2" %%a in (
    'WMIC Path Win32_Battery Get BatteryStatus /format:textvaluelist.xsl' 
) do @if "BatteryStatus"=="%%a" call :DoStaff "%%b" 
:DoStaff 
IF %~1 EQU 2 (
    if %count% NEQ 0 (
     set count=0 
     netsh interface set interface name="Wi-Fi" admin=enabled 
     netsh wlan connect name=GUEST 
     REM will delay execution of the next command by 10 seconds 
     TIMEOUT /T 10 
    ) 
) 
IF %~1 NEQ 2 (
    set /a count=%count%+1 
    if %count% EQU 1 (
     REM Disable the wireless interface 
     netsh interface set interface name="Wi-Fi" admin=disabled 
    ) 
) 
TIMEOUT /T 60 /NOBREAK > nul 
GOTO :LOOP 
+0

Возможно, непрерывная рекурсия заполняет вашу стеке памяти? Просто гадать здесь. Как вы запускаете файл VBS? Они запускают друг друга, или вы используете планировщик задач Windows? – vacip

+0

Я использовал задачу windows schedular для запуска файла .vbs – L22222

+0

О, извините, я думал, что вы перезапускаете пакетный файл снова и снова.Тогда это не так, вы просто запускаете его один раз, правильно? – vacip

ответ

4
@ECHO OFF 
set count=0 
:LOOP 
REM To Check the battery status, providing that 1 is discharging and 2 is connected to the AC 
for /F "delims== tokens=1,2" %%a in ('WMIC Path Win32_Battery Get BatteryStatus /format:textvaluelist.xsl') do @if "BatteryStatus"=="%%a" call :DoStaff "%%b" 

:: You are CALLing the following routine. 
:: IF the routine was to terminate then batch would return to here on termination. 
:: BUT the routine doesn't terminate - it loops back to LOOP 
:: (Which invokes another CALL, loop back to LOOP) ad infinitum 
:: eventually, you run out of stack space and the batch terminates. 

:: Fix : Loop back here 

GOTO LOOP 

:DoStaff 
IF %~1 EQU 2 (
    if %count% NEQ 0 (
    set count=0 
    netsh interface set interface name="Wi-Fi" admin=enabled 
    netsh wlan connect name=EPFL-GUEST 
    REM will delay execution of the next command by 10 seconds 
    TIMEOUT /T 10 
) 
) 
IF %~1 NEQ 2 (
    set /a count=%count%+1 
     if %count% EQU 1 (
     REM Disable the wireless interface 
     netsh interface set interface name="Wi-Fi" admin=disabled 
) 
) 
TIMEOUT /T 60 /NOBREAK > nul 

:: Here you need to terminate the subroutine. 
:: You could simply make thsi end-of-file, 
:: But this following line forces the issue. 
:: note that the colon before EOF is mandatory. 
:: batch understands "GOTO :EOF" to mean, very specifically, 
:: Go To End of physical file 

GOTO :EOF 

:: This following gotoline is not needed. it should be deleted. 
GOTO :LOOP 

Каждый раз, когда вы CALL подпрограмму, добавить еще 1 адрес возврата в стек. Поскольку вы никогда не завершаете подпрограмму (путем достижения конца файла или оператора EXIT), вы в конечном итоге исчерпаете пространство стека.

+1

да. Кроме того, может потребоваться отсроченное расширение с '% count%' (в ветке 'NEQ'). Зависит, если вы хотите отключить первое или второе уведомление об потери питания – Stephan

+0

Благодарим вас за объяснение. Я понимаю поток, но что, если моя ситуация требует, чтобы циклы продолжали цикл без остановки, даже если стек заполнен. я имею в виду, есть ли способ идентифицировать до того, как стек станет полным, чтобы снова запустить операцию? – L22222

+0

Удалив последний оператор Go to loop, я завершаю этот пакетный скрипт после обнаружения события !!! это не тот случай, когда моя партия предназначена для моей партии. Электричество может сократиться, затем может вернуться назад, затем разрезать, а затем вернуться назад. Мне нужен пакетный файл для непрерывного запуска, выполняется ли какое-либо условие или нет! – L22222

3

Если я правильно понял ваш сценарий, вы хотите отключить свой беспроводной адаптер, если компьютер включен, и снова включите его при возврате питания. Моя рекомендация будет сократить код в пакетном скрипте для переключения адаптер включения/выключения:

@echo off 

set "interface=Wi-Fi" 
set "network=EPFL-GUEST" 

REM get battery state (1 => discharging, 2 => connected to AC) 
for /f "delims== tokens=1,2" %%a in (
    'wmic Path Win32_Battery Get BatteryStatus /format:textvaluelist.xsl' 
) do if "BatteryStatus"=="%%a" set "BatteryState=%%b" 

REM get wireless interface state 
for /f "tokens=3" %%a in (
    'netsh interface show interface "%interface%" ^| find /i "administrative state"' 
) do set "InterfaceState=%%~a" 

if %BatteryState% equ 2 (
    if /i "%InterfaceState%"=="disabled" (
     netsh interface set interface name="%interface%" admin=enabled 
     netsh wlan connect name="%network%" 
    ) 
) else if /i "%InterfaceState%"=="enabled" (
    netsh interface set interface name="%interface%" admin=disabled 
) 

и изменить запланированное задание для запуска пакетного сценария (без пусковой VBScript) при запуске, повторяя каждую минуту на неопределенное время ,

Scheduled Task trigger: Begin at startup, repeat every minute indefinitely.

Задача также должна быть настроена на запуск того, зарегистрирован пользователь или нет (ваш счет нуждается в "log on as batch job" privilege для этого).

Scheduled Task setting: Run whether user is logged on or not, don't store the password.

+0

Оценка! но представьте себе, что мне нужно каждый раз сообщать мне sms о том, что электричество выключено, то есть всякий раз, когда он отключит беспроводной адаптер, чтобы расстрелять меня по электронной почте об этом! так что каждую минуту я ожидал, что он отправит мне электронное письмо всякий раз, когда произойдет сбой в электроснабжении, когда мне нужно только один раз в этой ситуации, и однажды, когда адаптер снова включится! поэтому ваш путь не подходит для моего сценария! – L22222

+0

@ L22222 Если вы внимательно рассмотрите сценарий, вы можете заметить, что 'netsh' зависит от 2 условий: от батареи * и * беспроводной включен = выключить, включить AC * и * wireless off =>. Сценарий не предпринимает действий для ситуаций «на батарее и беспроводной сети» или «на переменном токе и без wirless on». –

3

Я предпочитаю Ansgar's solution. Но вы можете заставить свой оригинальный дизайн работать.

Magoo identified why your script eventually fails, но есть дополнительная ошибка в вашей логике.

Вы инициализируете count на 0, что означает, что вы предполагаете, что при запуске подключается как AC, так и WiFi.

Но если AC подключен и WiFi отключен, тогда ваш код никогда не будет включать WiFi.

Вот один из способов устранить проблему.

@echo off 

:: Force the initial iteration to always enable or disable WiFi 
set "priorState=0" 

:LOOP 
for /F "delims== tokens=1,2" %%a in (
    'WMIC Path Win32_Battery Get BatteryStatus /format:textvaluelist.xsl' 
) do if "%%a"=="BatteryStatus" call :DoStuff "%%b" 
goto :LOOP 

:DoStuff 
if %~1 neq %priorState% (
    if %~1 equ 2 (
     %= Connected to AC, so enable WiFi =% 
     netsh interface set interface name="Wi-Fi" admin=enabled 
     netsh wlan connect name=EPFL-GUEST 
    ) else (
     %= Discharging battery, so disable WiFi =% 
     netsh interface set interface name="Wi-Fi" admin=disabled 
    ) 
    set "priorState=%~1" 
) 
timeout /t 60 /nobreak > nul 
exit /b 

можно поместить все в одном бесконечном FOR/L петли, так что не ЗОВ и не GOTO не требуется. Однако необходимо использовать задержанное расширение, чтобы в цикле отображалось изменение значения priorState.

@echo off 
setlocal enableDelayedExpansion 

:: Force the initial iteration to always enable or disable WiFi 
set "priorState=0" 

:: Infinite loop 
for /l %%N in() do (
    for /f "delims== tokens=1,2" %%A in (
    'wmic path Win32_Battery get BatteryStatus /format:textvaluelist.xsl' 
) do if "%%A"=="BatteryStatus" if "%%B" neq "!priorState!" (
    %= Battery state has changed =% 
    if %%B equ 2 (
     %= Connected to AC, so enable WiFi =% 
     netsh interface set interface name="Wi-Fi" admin=enabled 
     netsh wlan connect name=EPFL-GUEST 
    ) else (
     %= Discharging battery, so disable WiFi =% 
     netsh interface set interface name="Wi-Fi" admin=disabled 
    ) 
    set "priorState=%~1" 
) 
    timeout /t 60 /nobreak > nul 
) 
+0

Вы и Магу заканчиваете этот скрипт всякий раз, когда каждое из условий является мной, т. Е.Обнаружен AC или аккумулятор, выполните код, а затем завершите сценарий. это не мой сценарий! AC может быть обнаружен сейчас, но через некоторое время ноутбук может работать от батареи, а через некоторое время AC может вернуться обратно. когда нет проверки продолжительности для этих состояний, как узнать о произошедшем изменении мощности ноутбука! – L22222

+0

@ L22222 - прочитайте документацию и проверьте код, который мы вам предоставили. Черт, у моего последнего набора кода даже нет EXIT/B, так почему вы думаете, что он закончится? EXIT/B в конце моего первого кода завершает подпрограмму так, чтобы она возвращалась к основному циклу. Он не завершает сценарий. Основной цикл находится в бесконечном цикле GOTO. Но если вы приложите немного усилий, вы могли бы открыть это для себя. – dbenham

Смежные вопросы