Я запускаю пакетный файл с длительным сроком действия. Теперь я понимаю, что мне нужно добавить еще несколько команд в конце командного файла (без изменений в существующем контенте, а также в некоторых дополнительных командах). Можно ли это сделать, учитывая, что большинство командных файлов считываются инкрементально и выполняются один за другим? Или система считывает все содержимое файла, а затем запускает задание?Изменение командного файла при его запуске
ответ
Я просто попытался его, и против своей интуиции, она подобрала новые команды в конце (на Windows XP)
Я создал пакетный файл, содержащий
echo Hello
pause
echo world
Я побежал файл, и в то время как она была приостановлена, добавил
echo Salute
Сохраненный его и прижала ввести в Contine паузу, все три подсказки были повторены на консоль.
Итак, идите!
Командный интерпретатор запоминает позицию линии, в которой он находится в пакетном файле. Пока вы изменяете командный файл после текущей позиции линии, вы будете в порядке.
Если вы измените его до этого, он начнет делать странные вещи (повторяющиеся команды и т. Д.).
Является ли это документированным где угодно, или это из вашего собственного опыта? – Benoit
Это верно в моем опыте. – UnhandledExcepSean
На самом деле, что он будет делать, указатель синтаксического анализатора останется в том же индексе в файле, поэтому добавление/удаление текста перед индексом сдвинет то, что находится под указателем инструкции. Действительно, странные вещи случаются. – cat
Почти как rein said, cmd.exe запомнить позицию файла (а не только позицию строки), в которой она находится в данный момент, а также для каждого вызова она нажимает позицию файла в невидимом стеке.
Это означает, что вы можете редактировать файл, пока он работает позади и до фактического положения файла, вам нужно только то, что вы делаете ...
Небольшой образца из собственных модифицирующих партий
Он изменяет линию set value=1000
пример непрерывно
@echo off
setlocal DisableDelayedExpansion
:loop
REM **** the next line will be changed
set value=1000
rem ***
echo ----------------------
echo The current value=%value%
<nul set /p ".=Press a key"
pause > nul
echo(
(
call :changeBatch
rem This should be here and it should be long
)
rem ** It is neccessary, that this is also here!
goto :loop
rem ...
:changeBatch
set /a n=0
set /a newValue=value+1
set /a toggle=value %% 2
set "theNewLine=set value=%newValue%"
if %toggle%==0 (
set "theNewLine=%theNewLine% & rem This adds 50 byte to the filesize.........."
)
del "%~f0.tmp" 2> nul
for /F "usebackq delims=" %%a in ("%~f0") DO (
set /a n+=1
set "line=%%a"
setlocal EnableDelayedExpansion
if !n!==5 (
(echo !theNewLine!)
) ELSE (
(echo !line!)
)
endlocal
) >> "%~f0.tmp"
(
rem the copy should be done in a parenthesis block
copy "%~f0.tmp" "%~f0" > nul
if Armageddon==TheEndOfDays (
echo This can't never be true, or is it?
)
)
echo The first line after the replace action....
echo The second line comes always after the first line?
echo The current filesize is now %~z0
goto :eof
+1 Это забавный пример того, что возможно :) – dbenham
Джеба много удовольствия, но это очень сильно зависит от длины текста, который добавляется или удаляется. Я думаю, что контр-интуитивные результаты - это то, что означало подпора, когда он сказал: «Если вы измените его до этого, он начнет делать странные вещи (повторяя команды и т. Д.)».
Я изменил код jeb, чтобы показать, как динамический код переменной длины может быть свободно изменен в начале исполняемого командного файла до тех пор, пока выполняется соответствующее заполнение. Вся динамическая секция полностью заменяется каждой итерацией. Каждая динамическая строка имеет префикс без помех ;
. Это удобно разрешать FOR /F
, чтобы удалить динамический код из-за неявного параметра EOL=;
.
Вместо поиска определенного номера строки, я ищу конкретный комментарий, чтобы найти, где начинается динамический код. Это проще в обслуживании.
Я использую линии равных знаков, чтобы безвредно использовать код для расширения и сжатия. Может использоваться любая комбинация следующих символов: запятая, точка с запятой, равная, пробел, табуляция и/или новая строка. (Конечно, отступы не могут начинаться с точки с запятой.) Знаки равенства в круглых скобках допускают расширение кода. Знаки равенства после круглых скобок допускают сокращение кода.
Отметьте, что FOR /F
полоски пустые линии.Это ограничение можно преодолеть, используя FINDSTR, чтобы префикс каждой строки с номером строки, а затем разделил префикс в цикле. Но дополнительный код замедляет работу, поэтому делать это не стоит, если код не зависит от пустых строк.
@echo off
setlocal DisableDelayedExpansion
echo The starting filesize is %~z0
:loop
echo ----------------------
::*** Start of dynamic code ***
;set value=1
::*** End of dynamic code ***
echo The current value=%value%
::
::The 2 lines of equal signs amount to 164 bytes, including end of line chars.
::Putting the lines both within and after the parentheses allows for expansion
::or contraction by up to 164 bytes within the dynamic section of code.
(
call :changeBatch
==============================================================================
==============================================================================
)
================================================================================
================================================================================
set /p "quit=Enter Q to quit, anything else to continue: "
if /i "%quit%"=="Q" exit /b
goto :loop
:changeBatch
(
for /f "usebackq delims=" %%a in ("%~f0") do (
echo %%a
if "%%a"=="::*** Start of dynamic code ***" (
setlocal enableDelayedExpansion
set /a newValue=value+1, extra=!random!%%9
echo ;set value=!newValue!
for /l %%n in (1 1 !extra!) do echo ;echo extra line %%n
endlocal
)
)
) >"%~f0.tmp"
::
::The 2 lines of equal signs amount to 164 bytes, including end of line chars.
::Putting the lines both within and after the parentheses allows for expansion
::or contraction by up to 164 bytes within the dynamic section of code.
(
move /y "%~f0.tmp" "%~f0" > nul
==============================================================================
==============================================================================
)
================================================================================
================================================================================
echo The new filesize is %~z0
exit /b
Вышеуказанные работы, но все гораздо проще, если динамический код перемещается в подпрограмму в конце файла. Код может расширяться и сокращаться без ограничений и без необходимости заполнения. FINDSTR намного быстрее, чем FOR/F при удалении динамической части. Динамические линии можно безопасно префикс с точкой с запятой (включая метки!). Затем опция FINDSTR/V используется для исключения строк, начинающихся с точки с запятой, и новый динамический код можно просто добавить.
@echo off
setlocal DisableDelayedExpansion
echo The starting filesize is %~z0
:loop
echo ----------------------
call :dynamicCode1
call :dynamicCode2
echo The current value=%value%
call :changeBatch
set /p "quit=Enter Q to quit, anything else to continue: "
if /i "%quit%"=="Q" exit /b
goto :loop
:changeBatch
(
findstr /v "^;" "%~f0"
setlocal enableDelayedExpansion
set /a newValue=value+1, extra=!random!%%9
echo ;:dynamicCode1
echo ;set value=!newValue!
echo ;exit /b
echo ;
echo ;:dynamicCode2
for /l %%n in (1 1 !extra!) do echo ;echo extra line %%n
echo ;exit /b
endlocal
) >"%~f0.tmp"
move /y "%~f0.tmp" "%~f0" > nul
echo The new filesize is %~z0
exit /b
;:dynamicCode1
;set value=33
;exit /b
;
;:dynamicCode2
;echo extra line 1
;exit /b
EDIT - я изменил последний код, чтобы продемонстрировать, что даже метки могут быть префиксными, поэтому их можно легко включить в динамический код. – dbenham
Короткий ответ: да, пакетные файлы могут изменять себя во время работы. Как уже подтвердили другие.
Годы и годы назад, перед Windows 3, место, в котором я работал, имело внутреннюю систему меню в MS-DOS. То, как он управлял вещами, был довольно изящным: он фактически запускался из командного файла, который основная программа (написанная на языке C) модифицирована для запуска скриптов. Этот трюк означал, что сама программа меню не занимала память, пока выполнялись выборы. И это включало такие вещи, как программа LAN Mail и терминальная программа 3270.
Но запуск из самомодулируемого командного файла означал, что его скрипты также могут выполнять такие функции, как загрузка программ TSR, и на самом деле могли бы сделать практически все, что можно было бы добавить в пакетный файл. Это сделало его очень мощным. Только команда GOTO
не работала, пока автор в конечном итоге не выяснил, как сделать командный файл перезагрузкой для каждой команды.
Командный интерпретатор, как представляется, помнит смещение байта в каждом командном файле, который он считывает, но сам файл не заблокирован, поэтому можно внести изменения, скажем, с помощью текстового редактора, пока он запущен.
Если после этого запомненного местоположения произошло изменение файла, интерпретатор должен с радостью продолжить выполнение измененного скрипта. Однако, если изменение сделано до этой точки, и эта модификация изменяет длину текста в этой точке (например, вы вставили или удалили какой-либо текст), это запоминающееся местоположение теперь больше не относится к началу следующей команды , Когда интерпретатор пытается прочитать следующую «строку», он вместо этого возьмет другую строку или, возможно, часть строки в зависимости от того, сколько текста было вставлено или удалено. Если вам повезет, он, вероятно, не сможет обработать любое слово, с которым он столкнулся, дать ошибку и продолжить выполнение со следующей строки - но все же, вероятно, не то, что вы хотите.
Однако, понимая, что происходит, вы можете структурировать свои сценарии, чтобы снизить риск. У меня есть сценарии, которые реализуют систему простого меню, отображая меню, принимая ввод от пользователя с помощью команды choice
, а затем обрабатывая выбор. Хитрость заключается в том, чтобы убедиться, что точка, в которой сценарий ожидает ввода, находится ближе к верхней части файла, так что любые изменения, которые вы, возможно, захотите сделать, произойдут после этой точки и не будут иметь неприятных ударов.
Пример:
:top
call :displayMenu
:prompt
REM The script will spend most of its time waiting here.
choice /C:1234 /N "Enter selection: "
if ERRORLEVEL == 4 goto DoOption4
if ERRORLEVEL == 3 goto DoOption3
if ERRORLEVEL == 2 goto DoOption2
goto DoOption1
:displayMenu
(many lines to display menu)
goto prompt
:DoOption1
(many lines to do Option 1)
goto top
:DoOption2
(many lines to do Option 2)
goto top
(etc)
- 1. Окно PowerShell при запуске из командного файла
- 2. Показывать неопределенный JProgressBar при запуске командного файла
- 3. Ошибка при запуске командного файла с параметрами
- 4. Запуск командного файла при запуске excel
- 5. Скрытие CMD при запуске командного файла
- 6. Изменение атрибута файла с помощью командного файла
- 7. как не открывать окно Cmd при запуске командного файла
- 8. Изменение командного файла из другого пакетного файла
- 9. VBScript зависает при запуске командного файла с запуском WShell.Script
- 10. Получение разрешения отклонено при запуске _zipit.vbs из командного файла
- 11. Закрытие окна, которое появляется при запуске командного файла
- 12. Powershell процесс «висит» при запуске удаленного командного файла
- 13. запуск командного файла, но команды не запускаются при запуске c.
- 14. Как добавить данные в файл журнала при запуске командного файла
- 15. Как скрыть консоль при запуске командного файла в окнах
- 16. Изменение формата текстового файла при запуске пакета
- 17. Запуск командного файла из java вызывает зависание, но не при его запуске
- 18. Изменение нескольких файлов командного файла не работает
- 19. Изменение имени системы с помощью командного файла
- 20. Ошибка при выполнении командного файла
- 21. Изменение @RequestMappings при запуске
- 22. Закрытие приложения и запуск его командного файла?
- 23. Интерактивные проблемы командного файла
- 24. Запуск командного файла из другого командного файла
- 25. Запуск командного файла с использованием командного файла
- 26. Как остановить сохранение командного файла командного файла
- 27. Изменение размера сцены при запуске
- 28. Как установить приоритет процесса при запуске исполняемого файла из командного файла в Windows без запуска терминала
- 29. Закрытие командного окна при выполнении команды gradle из командного файла
- 30. Запуск командного файла java-кода
Вы должны любить так быстро ответы. Вы уже запустили пакет> опубликованный вопрос> получили ответ> отредактировали файл до завершения выполнения! –
Также обратите внимание, что когда пакетный файл удаляется или переименовывается, момент, когда текущая команда завершила ошибку, будет выдана: «Пакетный файл не может быть найден». –