Обнаружение открытия файла в командном файле
Скажем, у меня есть командный файл для выполнения длинной сборки, и в конце он создает EXE. Если я забуду закрыть приложение перед тем, как начать сборку, фаза соединения завершится неудачно, если не удастся заново создать EXE-файл.
Я хочу проверить, открыт ли EXE в начале сборки. Я попытался переименовать файл EXE для себя, но, хотя это приводит к ошибке отказа в доступе, команда переименования (являющаяся внутренней командой) не устанавливает%ErrorLevel%.
Что такое неразрушающий способ проверки открытого файла, который устанавливает% ErrorLevel% в ненулевое значение?
3 ответа
Метод переименования у меня не работал (проверено на Windows XP SP3). Я запустил произвольное приложение и попытался переименовать его себе. Там не было никакой ошибки, никакого эффекта вообще.
Тем не менее, этот метод работал:
COPY /B app.exe+NUL app.exe
Когда приложение работало, эта команда выдала мне сообщение об ошибке. И когда приложение было отключено, не только эта команда сохранила содержимое файла, но и оставила метку времени изменения без изменений.
Поэтому на вашем месте я бы, вероятно, использовал эту команду (в начале пакетного сценария, как вы сказали) следующим образом:
COPY /B app.exe+NUL app.exe >NUL || (GOTO :EOF)
||
оператор передает управление команде / блоку рядом с ним, если предыдущая команда не выполнена (поднял значение уровня ошибки). Таким образом, приведенная выше команда завершит работу сценария, если COPY не удалась (что было бы, если бы файл был открыт).
Сообщение об ошибке будет сохранено (поскольку такие сообщения обычно отправляются на так называемое стандартное устройство ошибки и не сбрасываются с >NUL
перенаправление, в то время как другие сообщения, не связанные с ошибками, обычно отправляются на стандартный вывод и поэтому могут быть подавлены с помощью >NUL
) и служит объяснением преждевременного прекращения действия сценария. Однако, если вы хотите отобразить собственное сообщение, вы можете попробовать что-то вроде этого:
COPY /B app.exe+NUL app.exe >NUL 2>NUL || (ECHO Target file inaccessible& GOTO :EOF)
В то время как >NUL
скрывает все, что отправлено на стандартный вывод, 2>NUL
делает то же самое для стандартной ошибки.
@echo off
:start
ren filename filename // rename file to same name
if errorlevel 1 goto errorline
echo command successfull file is not in use anymore
goto end
:errorline
echo Rename wasnt possible, file is in use try again in 5seconds
timeout /T 5
goto :start
:end
exit
переименовывает файл с тем же именем, если это возможно, сценарий переходит в конец, который завершает работу с кодом, в противном случае он выдает код ошибки 1 и переходит на строку ошибок, по истечении 5 секунд он переходит к:start и сценарий запускается с начала.
Нашли лучший способ:
:start
timeout /T 5
if exist %1 (
2>nul (
>> %1 (call )
) && (goto ende) || (goto start) ) else ( exit )
:ende
YourCode
Каждые 5 секунд будет проверяться, "используется ли файл", если он снова запустится. если нет, то это заканчивается, где вы можете сделать ваши следующие варианты