Как избежать нескольких экземпляров скрипта, позволяя запустить его снова без изменения заголовка - PullRequest
0 голосов
/ 23 октября 2018

У меня есть этот скрипт, который должен запускаться только в одном экземпляре.Мой способ убедиться, что этого не произойдет, -

tasklist /fi "imagename eq cmd.exe" /v | find "lootbot" && echo already running && pause && exit /b
title lootbot

, а затем выполнить корректный выход, чтобы скрипт мог быть перезапущен ...

:action8
cd /d "%~dp0"
title command prompt
echo type launch to return to lootbot
exit /b

проблема в том, что всякий раз, когдаСценарий вылетает из-за ошибки, он не позволит мне запустить его снова без предварительной ручной переустановки заголовка на что-то другое.

не большая проблема, конечно, но я собираю это длядругие люди, чтобы использовать, поэтому я ищу простые в использовании решения здесь.Я думаю, что если есть способ определить, называется ли в командной строке current lootbot, то этой проблемы можно было бы автоматически избежать.это весь сценарий на всякий случай.

@echo off
tasklist /fi "imagename eq cmd.exe" /v | find "lootbot" && echo lootbot already running, press a key to exit && pause && exit /b
title lootbot
:: enable save files location (persistant memory)
set "saves=%appdata%\lootbot"
if not exist "%saves%" mkdir "%saves%"
:: create/load saves, echo first
if exist "%saves%\echoes\launch" echo on
if not exist "%saves%\loopdelay" echo 300>"%saves%\loopdelay"
if not exist "%saves%\promptdelay" echo 60>"%saves%\promptdelay"
set /p loopdelay=<"%saves%\loopdelay" & set /p promptdelay=<"%saves%\promptdelay"
:: advanced prep
chcp 65001 >nul
set "path=%path%;%~dp0;c:\program files\filebot"
wmic process where name="cmd.exe" call setpriority "idle" >nul
:: additional scripts (all-in-one launcher)
start vpn.cmd

:: add "going legit" to vpn or somewhere (meaning close torrents and vpn, reactivate vpn if torrents appear, or close torrents)
:: add skippable delay here to auto-avoid possible mishandling ones being checked in qbittorrent
cls
:menu
@colorx -c 08
@if exist "%saves%\echoes\launch" echo on
@cd /d "%~dp0"
@set "msg=lootbot ready (%time:~0,2%:%time:~3,2%) wait %loopdelay%s or enter command"
@set "msg=%msg:( =(%" & rem this removes the blank space from early hours
@choice /t %loopdelay% /c rcplsjdq /n /d r /m "%msg% [R]un [C]lear [P]ause [L]ist [S]etup [J]obs [D]onate [Q]uit: "
:: add selective choices here, based on what scripts are available. might need those scripts to be names or placed different to autodetect
@goto action%errorlevel%
@goto menu

:action1
:routine
:: run now/default infinite loop
call report %~n0 import
call report %~n0 direct
:: idea: add small amount of random files to scan?
goto menu

:action2
:clear
cls
goto menu

:action3
pause
goto menu

:action4
:playlist
call report %~n0 player
goto menu

:action5
:settings
call report %~n0 option
goto menu

:action6
:caring
call report %~n0 caring
goto menu

:action7
:donate
call report %~n0 donate
goto menu

:action8
:exit
:: quit back to command prompt
cd /d "%~dp0"
title command prompt
echo use command launch to return to lootbot, bye!
exit /b

1 Ответ

0 голосов
/ 23 октября 2018

Это легко сделать, стратегически используя перенаправление с CALL для установки файла блокировки.Только один экземпляр может иметь доступ для записи в файл блокировки.Попытки второго экземпляра потерпят неудачу.Первый экземпляр снимет блокировку, как только выйдет, независимо от того, как он завершится.

Я использую несколько этапов перенаправления, чтобы скрыть нежелательные сообщения об ошибках, но основная подпрограмма имеет обычные stdout и stderr.Я добавляю %*, чтобы передать исходные аргументы основному.Единственная «странная» ситуация в main - это %0 вместо :main вместо исполняемого скрипта.Но %~f0 может использоваться для получения полного пути к исполняемому сценарию.

test.bat

@echo off
9>&2 2>nul (call :lockAndRestoreStdErr %* 8>"%~f0.lock") && (
  del "%~f0.lock"
) || (
  echo Only one instance allowed - "%~f0" is already running >&2
)
exit /b

:lockAndRestoreStdErr
call :main %* 2>&9
exit /b 0

:main
echo        %%0 = %0
echo    "%%~f0" = "%~f0"
echo Arguments = %*
pause
exit /b

Пример выходных данных экземпляра 1

C:\test>test arg1 arg2
       %0 = :main
   "%~f0" = "C:\test\test.bat"
Arguments = arg1 arg2
Press any key to continue . . .

Пример Экземпляр 2 выходного файла экземпляра 2 все еще работает

C:\test>test arg1 arg2
Only one instance allowed - "C:\test\test.bat" is already running

C:\test>

Экземпляр 1 прекратит работу после нажатия клавиши, а затем экземпляр 2 можетзапустите скрипт.

EDIT

На самом деле вам не нужен отдельный файл блокировки.Вы можете использовать сам пакетный скрипт в качестве файла блокировки.Просто не забудьте использовать >> вместо >, иначе вы уничтожите скрипт!

@echo off
9>&2 2>nul (call :lockAndRestoreStdErr %* 8>>"%~f0") || (
  echo Only one instance allowed - "%~f0" is already running >&2
)
exit /b

:lockAndRestoreStdErr
call :main %* 2>&9
exit /b 0

:main
echo        %%0 = %0
echo    "%%~f0" = "%~f0"
echo Arguments = %*
pause
exit /b

Если у пользователей нет прав на запись в скрипт, то ни один из вышеперечисленных не будет работать.В этом случае вы должны поместить файл блокировки в папку %temp%.

@echo off
9>&2 2>nul (call :lockAndRestoreStdErr %* 8>"%temp%\%~nx0.lock") && (
  del "%temp%\%~nx0.lock"
) || (
  echo Only one instance allowed - "%~f0" is already running >&2
)
exit /b

:lockAndRestoreStdErr
call :main %* 2>&9
exit /b 0

:main
echo        %%0 = %0
echo    "%%~f0" = "%~f0"
echo Arguments = %*
pause
exit /b

РЕДАКТИРОВАТЬ - Ответ на вопрос в комментарии

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

@echo off
9>&2 2>nul (call :lockAndRestoreStdErr %* 8>>"%~f0") || (
  echo Only one instance allowed - "%~f0" is already running >&2
  pause
)
exit /b

:lockAndRestoreStdErr
call :main %* 2>&9
exit /b 0

:main
title lootbot
:: enable save files location (persistant memory)
etc...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...