Есть ли способ убить проход цикла, который длится более 1 минуты, и перейти к следующему проходу цикла в пакетном режиме?
Скрипт jhove обработает все файлы %% a из моего каталога% input% в цикле for. Насколько я знаю, taskkill используется только для уничтожения файлов.exe, но не за один проход. Может ли этот код подождать 60 секунд, а затем завершить цикл и перейти к следующему? Так что как это timeout /t 1/nobreak>nul taskkill /F /IM "%%a"
for /f "tokens=*" %%a in ('dir /b /a-d /s %input%\*.*') do (
echo Verarbeite %%~na
CALL jhove -m PDF-hul -h xml -o "%output%\%%~na_!count!.xml" "%%a"
set /a count=count+1
set /a loop3+=1
)
1 ответ
Конечно, вы можете сделать что-то вроде этого:
> nul timeout /T 60 /NOBREAK
taskkill ...
Но это будет ждать 60 секунд, даже если процесс завершится до истечения этого времени.
Я бы использовал цикл опроса и запрос через tasklist
или нет, процесс все еще работает, и если нет, продолжите обработку следующего элемента. Вот возможный способ сделать это (см. Комментарии):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_INPUT=." & rem // (path to input directory)
set "_OUTPUT=." & rem // (path to output directory)
set "_MASK=*.*" & rem // (input file name pattern)
set "_SCRIPT=%~dp0jhove.bat" & rem // (script to process input files by)
set "_TITLE=JHOVE" & rem // (base window title of script process)
set "_FROZEN=" & rem // (only terminate frozen processes if not empty)
set /A "_TIMEOUT=60" & rem // (timeout value for process; zero means none)
set /A "COUNT=0"
rem // Resolve output directory:
for %%D in ("%_OUTPUT%") do (
rem // Iterate through all input files:
for /F "delims=" %%F in ('dir /S /B /A:-D "%_INPUT%\%_MASK%"') do (
rem // Process input files in a sub-routine:
call :RUN -m PDF-hul -h xml -o "%%~fD\%%~nF_%%COUNT%%.xml" "%%~F"
set /A "COUNT+=1"
)
)
endlocal
exit /B
:RUN
rem // Build unique window title:
set "WTITLE=%_TITLE%_%RANDOM%"
rem // Build image name from command prompt specification:
for %%I in ("%ComSpec%") do set "IMAGE=%%~nxI"
rem // Run script using unique window title:
start "%WTITLE%" /D "%_INPUT%" "%ComSpec%" /D /S /C ^""%_SCRIPT%" %*^"
rem // Skip polling loop in case timeout is set to zero, thus deactivated:
if %_TIMEOUT% leq 0 goto :END
rem // Set filter according to given configuration:
if defined _FROZEN (set "FILTER=/FI "STATUS ne RUNNING"") else set "FILTER="
rem // Try termination without forcing first:
set "FORCE="
rem // Reset timer:
set /A "TIMER=0"
rem // Reset error flag:
set "ERR=0"
:LOOP
rem // Retrieve PID of running command prompt process with unique window title:
set "PID=0"
for /F "tokens=1* delims=:" %%T in ('
2^> nul tasklist /FI "IMAGENAME eq %IMAGE%" /FI "WINDOWTITLE eq %WTITLE%" ^
/FO LIST /V
') do (
if "%%T"=="PID" for /F %%V in ("%%U") do set "PID=%%V"
if "%%T"=="Status" for /F "tokens=*" %%V in ("%%U") do set "STATUS=%%V"
)
rem // Skip loop if no PID has been found (process might already be finished):
if %PID% equ 0 goto :END
rem // Wait for a second, so this is the polling rate:
> nul timeout /T 1 /NOBREAK
rem // Increment timer:
set /A "TIMER+=1"
rem // Check whether timeout limit is reached, loop if not:
if %TIMER% leq %_TIMEOUT% goto :LOOP
rem /* Loop if process is frozen, if desired (this filter (`/FI`) cannot applied
rem to `taskkill` below, because mismatch would not set the exit code, hence
rem use of conditional operators `&&` and `||` would not work): */
if defined FILTER for /F "tokens=1* delims=:" %%T in ('
2^> nul tasklist /FI "IMAGENAME eq %IMAGE%" /FI "WINDOWTITLE eq %WTITLE%" ^
%FILTER% /FO LIST /V
') do if "%%T"=="INFO" goto :LOOP
rem /* Try to terminate process with found PID (`taskkill` sets the exit code in
rem case filters `/PID` or `/IM` deliver a mismatch, but not for `/FI`): */
> nul 2> nul taskkill /PID %PID% %FORCE% && (
rem // Termination succeeded, so return information message:
echo Successfully terminated process:
call :MSG %*
rem // Set error flag:
set "ERR=1"
) || (
rem // Termination failed:
if not defined FORCE (
rem // Normal termination failed, so try termination forcefully now:
set "FORCE=/F"
goto :LOOP
) else (
rem // Forceful termination failed, so return error message:
>&2 (
echo Failed to terminate process:
call :MSG %*
)
rem // Set error flag:
set "ERR=2"
)
)
:END
rem /* Exit with exit code (`ErrorLevel`) set to `0` if no process had to be
rem terminated, `1` if at least one process had to be terminated, and `2`
rem if at least one process could not be terminated (forcefully): */
exit /B %ERR%
:MSG
rem // Return some process details:
echo PID = %PID%
echo image name = %IMAGE%
echo status = %STATUS%
echo window title= %WTITLE%
echo command line= "%_SCRIPT%" %*
echo/
exit /B