В основном вы не можете в добром духе.
Прежде всего потому, что это не тривиально. Вы должны найти правильный процесс cmd.exe, когда в общем случае «сделать все правильно» не так просто.
Во-вторых, прекращение может быть недостаточным для остановки сценария, поскольку один сценарий может запускать другой сценарий в цикле, поэтому простое завершение одного не приведет к завершению другого. Более того, это может привести к сбою выполнения, потому что вам нужно завершить все дерево процессов из корня «атомарно», чтобы правильно остановить выполнение.
Вместо «поиск прервать» вы можете просто «не выполнять, если уже запущен». Техника та же, что и в сценариях оболочки Unix: попробуйте создать какой-то уникальный каталог и заблокировать его от удаления путем перенаправления записи в файл в этом каталоге.
Я использую имена сценариев, например, exec_once_or_exit.bat:
@echo off
setlocal
set "LOCK_DIR_NAME_SUFFIX=%DATE%_%TIME%"
set "LOCK_DIR_NAME_SUFFIX=%LOCK_DIR_NAME_SUFFIX::=_%"
set "LOCK_DIR_NAME_SUFFIX=%LOCK_DIR_NAME_SUFFIX:/=_%"
set "LOCK_DIR_NAME_SUFFIX=%LOCK_DIR_NAME_SUFFIX:-=_%"
set "LOCK_DIR_NAME_SUFFIX=%LOCK_DIR_NAME_SUFFIX:.=_%"
set "LOCK_DIR_NAME_SUFFIX=%LOCK_DIR_NAME_SUFFIX:,=_%"
set LASTERROR=0
rem cleanup if leaked by crash or ctrl-c, won't be removed if already acquired because of write redirection lock
rmdir /S /Q "%TEMP%\lock_%~1" >nul 2>&1
mkdir "%TEMP%\lock_%~1" && (
rem IMPL to use "goto :EOF" in next command instead of "exit /b %ERRORLEVEL%" under "block" command - "( )"
call :IMPL %%*
goto :EOF
)
exit /b -1024
:IMPL
rem call IMPL2 to recover exit code from commands like "exit /b"
call :IMPL2 %%* 9> "%TEMP%\lock_%~1\lock0_%LOCK_DIR_NAME_SUFFIX%.txt"
set LASTERROR=%ERRORLEVEL%
rmdir /S /Q "%TEMP%\lock_%~1"
exit /b %LASTERROR%
:IMPL2
rem a batch script must be always call over the "call" prefix
if "%~n2" == "bat" call %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9 && goto :EOF
if not "%~n2" == "bat" (
%2 %3 %4 %5 %6 %7 %8 %9
)
goto :EOF
Использование:
exec_once_or_exit.bat <UniqueNameForLock> <PathToExecutable> <8Arguments>
exec_once_or_exit.bat <UniqueNameForLock> <BatchCommand(s)>
Пояснение:
Команда mkdir вернет ненулевой код завершения, если каталог уже существует или не может быть создан по какой-либо причине, и 0, если он создан.
LOCK_DIR_NAME_SUFFIX используется, чтобы иметь уникальное имя для файла в каталоге. Использует все эти замены над определенными символами, потому что формат переменной% DATE% и% TIME% зависит от формата даты и времени на странице локализации Windows.
Перенаправление через идентификатор потока 9 используется для блокировки файла в каталоге для записи и, таким образом, блокирует сам родительский каталог от удаления. Если поток по какой-либо причине не может быть перенаправлен, сценарий немедленно завершается с помощью cmd.exe без дальнейшего выполнения, которого достаточно для взаимного исключения выполнения. Таким образом, поскольку перенаправление происходит до выполнения, нет опасения, что что-то может быть выполнено до перенаправления.
Если произошел сбой или ctrl-c, то каталог останется в хранилище (hdd, ssd, что-либо еще), поэтому для его очистки в этом случае скрипт пытается удалить весь каталог со всеми файлами внутри, прежде чем Мкдир.
Единственное, что может случиться здесь неправильно, это то, что никто не может добиться исполнения, которое, кажется, случается не так часто. По крайней мере, это лучше, чем «больше, чем один за один раз».