Estoy ejecutando un archivo por lotes de ejecución larga. Ahora me doy cuenta de que tengo que agregar algunos más comandos al final del archivo por lotes (no hay cambios en el contenido existente, solo algunos comandos adicionales). ¿Es posible hacer esto, dado que la mayoría de los archivos por lotes se leen de forma incremental y se ejecutan uno por uno? ¿O el sistema lee todo el contenido del archivo y luego ejecuta el trabajo?Cambiar un archivo por lotes cuando se está ejecutando
Respuesta
yo sólo lo han probado, y en contra de mi intuición, se recogieron los nuevos comandos al final (en Windows XP)
he creado un archivo por lotes que contiene
echo Hello
pause
echo world
me encontré con el archivo, y al mismo tiempo en que se interrumpió, agregó
echo Salute
guardado y pulsa eNTER para contine la pausa, los tres indicaciones se hicieron eco de la consola.
Así que, ¡adelante!
El intérprete de comandos recuerda la posición de línea en el archivo por lotes. Siempre que modifiques el archivo por lotes después de la posición actual de la línea de ejecución, estarás bien.
Si lo modifica antes, entonces comenzará a hacer cosas extrañas (repetir comandos, etc.).
¿Está documentado en alguna parte, por favor o es por su propia experiencia? – Benoit
Esto es cierto en mi experiencia. – UnhandledExcepSean
En realidad, lo que hará es que el puntero del analizador permanecerá en el mismo índice en el archivo, por lo que agregar/eliminar texto antes del índice cambiará lo que está debajo del puntero de instrucción. Cosas raras suceden, de hecho. – cat
Casi como rein dijo, cmd.exe recuerda la posición del archivo (no solo la posición de línea) que es actualmente, y también para cada llamada empuja la posición del archivo en una pila invisible.
Eso significa, puede editar su archivo mientras se está ejecutando detrás y delante de la posición real del archivo, sólo necesita lo que haces ...
Una pequeña muestra de un lote de auto modificación
Cambia la línea set value=1000
ejemplo continuamente
@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 Ese es un ejemplo divertido de lo que es posible :) – dbenham
de Jeb es un montón de diversión, pero es muy dependiente de la longitud del texto que se añade o se elimina. Creo que los resultados contrarios a la intuición son lo que quiso decir cuando dijo "Si lo modificas antes, entonces comenzará a hacer cosas extrañas (repetir comandos, etc.)".
Modifiqué el código de jeb para mostrar cómo se puede modificar libremente el código dinámico de longitud variable al comienzo de un archivo por lotes en ejecución, siempre que el relleno apropiado esté en su lugar. Toda la sección dinámica se reemplaza por completo con cada iteración. Cada línea dinámica tiene el prefijo ;
que no interfiere. Esto permite convenientemente FOR /F
quitar el código dinámico debido a la opción implícita EOL=;
.
En lugar de buscar un número de línea particular, busco un comentario específico para ubicar dónde comienza el código dinámico. Esto es más fácil de mantener.
Utilizo líneas de signos iguales para rellenar el código de forma inofensiva y permitir la expansión y la contracción. Se puede usar cualquier combinación de los siguientes caracteres: coma, punto y coma, igual, espacio, pestaña y/o nueva línea. (Por supuesto, el relleno no puede comenzar con un punto y coma.) Los signos de igual dentro de los paréntesis permiten la expansión del código. Los signos de igual después del paréntesis permiten la contracción del código.
Tenga en cuenta que FOR /F
elimina las líneas vacías.Esta limitación se puede superar mediante el uso de FINDSTR para prefijar cada línea con el número de línea y luego quitar el prefijo dentro del ciclo. Pero el código adicional ralentiza las cosas, por lo que no vale la pena hacerlo a menos que el código dependa de líneas en blanco.
@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
Los trabajos anteriores, pero las cosas son mucho más fáciles si el código dinámico se mueve a una subrutina al final del archivo. El código puede expandirse y contraerse sin limitación, y sin la necesidad de relleno. FINDSTR es mucho más rápido que FOR/F para eliminar la parte dinámica. Las líneas dinámicas pueden ser prefijadas con un punto y coma (incluidas las etiquetas). Luego, la opción FINDSTR/V se usa para excluir líneas que comienzan con un punto y coma y el nuevo código dinámico puede simplemente anexarse.
@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
EDITAR - Modifiqué el último código para demostrar que incluso las etiquetas pueden tener prefijos, por lo que pueden incluirse fácilmente en el código dinámico. – dbenham
Respuesta breve: sí, los archivos por lotes se pueden modificar mientras se están ejecutando. Como otros ya han confirmado.
Hace años y años, antes de Windows 3, el lugar donde trabajaba tenía un sistema de menú interno en MS-DOS. La forma en que ejecutó las cosas fue bastante elegante: en realidad se ejecutó desde un archivo por lotes que el programa principal (escrito en C) modificó para ejecutar scripts. Este truco significaba que el programa de menú no ocupaba espacio en la memoria mientras se ejecutaban las selecciones. Y esto incluía cosas como el programa LAN Mail y el programa de terminal 3270.
Pero al ejecutar desde un archivo por lotes auto-modificable, sus scripts también podían hacer cosas como cargar programas TSR y de hecho podían hacer casi cualquier cosa que pudieras poner en un archivo por lotes. Lo que lo hizo muy poderoso. Solo el comando GOTO
no funcionó, hasta que el autor eventualmente descubrió cómo hacer que el archivo por lotes se reiniciara para cada comando.
El intérprete de comandos parece recordar el desplazamiento de bytes dentro de cada archivo de comando que está leyendo, pero el archivo no está bloqueado, por lo que es posible realizar cambios, por ejemplo con un editor de texto, mientras se está ejecutando.
Si se realiza un cambio en el archivo después de esta ubicación recorrida, el intérprete debería continuar ejecutando el script modificado. Sin embargo, si el cambio se realiza antes de ese punto, y esa modificación cambia la longitud del texto en ese punto (por ejemplo, ha insertado o eliminado algún texto), esa ubicación recordada ya no se refiere al inicio de ese siguiente comando . Cuando el intérprete intenta leer la siguiente "línea", en lugar de eso recoge una línea diferente, o posiblemente parte de una línea, según la cantidad de texto insertado o eliminado. Si tiene suerte, probablemente no podrá procesar la palabra en la que aterrice, generará un error y continuará ejecutándose desde la siguiente línea, pero probablemente no sea lo que usted desea.
Sin embargo, con la comprensión de lo que está sucediendo, puede estructurar sus secuencias de comandos para reducir el riesgo. Tengo scripts que implementan un sistema de menú simple, mostrando un menú, aceptando la entrada del usuario usando el comando choice
y luego procesando la selección. El truco consiste en asegurarse de que el punto donde el script espera la entrada está cerca de la parte superior del archivo, de modo que cualquier edición que desee realizar se producirá después de ese punto y, por lo tanto, no tendrá ningún impacto desagradable.
Ejemplo:
: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. Ejecutando archivo por lotes en segundo plano cuando Windows inicia
- 2. Ejecutando rake desde el archivo por lotes
- 3. Dentro de un archivo por lotes, ¿cómo puedo saber si se está ejecutando un proceso?
- 4. Ejecutando vbscript desde el archivo por lotes
- 5. Cygwin ejecutando secuencia de comandos de un archivo por lotes?
- 6. Ejecutando un archivo por lotes en el shell git
- 7. Incluir un archivo por lotes en un archivo por lotes
- 8. ¿Cómo comprobar si un servicio se está ejecutando a través de un archivo por lotes e iniciarlo, si no se está ejecutando?
- 9. de archivos por lotes para comprobar si un servicio del sistema se está ejecutando
- 10. ¿Qué sucederá cuando edite un script mientras se está ejecutando?
- 11. Ejecutando un script por lotes en el cierre de Windows
- 12. cómo saber en qué versión de Windows y/o cmd.exe se está ejecutando un archivo por lotes?
- 13. Rails js.erb archivo no se está ejecutando
- 14. ejecutando un comando por lotes a través del trabajo SSIS
- 15. Comprueba si se está ejecutando un archivo exe específico
- 16. jQuery funciona en Firefox cuando Firebug se está ejecutando, no funciona cuando Firebug NO se está ejecutando
- 17. Ejecutando un script por lotes haciendo clic derecho en cualquier archivo
- 18. Ejecutar archivo por lotes tras otro archivo por lotes se completa
- 19. ejecutando R en modo por lotes - ¿imprimir en pantalla?
- 20. Codificación de archivo por lotes
- 21. Detectando cómo se ejecutó un archivo por lotes
- 22. Ventana de PowerShell cuando se inició desde un archivo por lotes
- 23. Crear un archivo por lotes para copiar y cambiar el nombre del archivo
- 24. Ejecute el archivo por lotes como un servicio de Windows
- 25. Ejecutando cadena variable como comando en el proceso por lotes
- 26. ejecutar un archivo por lotes desde C#
- 27. ¿Cuánto demora ejecutar un archivo por lotes?
- 28. BroadcastReceiver cuando la aplicación no se está ejecutando
- 29. HttpWebRequest no funciona, excepto cuando se está ejecutando fiddler
- 30. Periodictask no se está ejecutando
Usted gotta love respuestas tan rápido. Ya comenzó a ejecutar el lote> publicó una pregunta> obtuvo una respuesta> editó su archivo antes de la ejecución completada. –
También tenga en cuenta que cuando se elimine o se cambie el nombre del archivo por lotes, en el momento en que finalice la instrucción actual se generará un error: "No se puede encontrar el archivo por lotes". –