Это легко сделать, стратегически используя перенаправление с 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...