Secuencia de comandos por lotes que se elimina
-
10-07-2019 - |
Pregunta
Tengo un script .bat
que inicia un programa java
.
El programa java
elimina la carpeta donde se encuentra .bat
.
No tengo forma de tocar el programa java
. Solo puedo modificar el archivo .bat
.
El problema es que el archivo .bat
, una vez eliminado, detiene su ejecución de inmediato sin finalizar.
Pero hay algunas tareas de limpieza que deben realizarse después de que el programa java
salga.
Traté de copiar el archivo .bat
en otro lugar y ejecutarlo en una ubicación donde no se eliminaría. Por desgracia, una vez que se elimina el .bat
original, porque todavía está en ejecución, ocurre el mismo bloqueo y no termina.
Aquí hay dos archivos de muestra (para el propósito del ejemplo, supongamos que se encuentran en D: \ tmp
):
delete.bat
echo "delete start"
pause
del launch.bat
pause
echo "delete end"
launch.bat
echo "launch start"
setlocal enabledelayedexpansion enableextensions
if "%CD%"=="C:\tmp" (
echo "in temp"
d:
cd \tmp
delete.bat
)
if "%CD%" NEQ "C:\tmp" (
echo "not in temp"
mkdir C:\tmp
copy launch.bat C:\tmp\launch.bat
echo "launch copied"
C:
cd \tmp
cmd /c launch.bat
)
echo "launch end"
El lanzamiento de launch.bat
funcionaría si la ejecución del launch.bat
copiado se separara del inicial.
¿Alguien sabe una manera de hacer que un .bat
termine su ejecución incluso si se elimina mientras se ejecuta?
Solución 4
Parece que tengo un mejor resultado al hacerlo así (llamando a launch.bat
con cmd / k
):
launch.bat
echo "launch start"
setlocal enabledelayedexpansion enableextensions
if "%CD%"=="C:\tmp" (
echo "in temp"
d:
cd \tmp
delete.bat
echo "after delete"
)
if "%CD%" NEQ "C:\tmp" (
echo "not in temp"
mkdir C:\tmp
copy launch.bat C:\tmp\launch.bat
echo "launch copied"
C:
cd \tmp
cmd /k launch.bat
)
echo "launch end"
Ahora puedo alcanzar el echo " después de eliminar "
, pero termino de alguna manera en un bucle infinito. Al menos mi limpieza se puede ejecutar en este punto. Sin embargo, no sé por qué no puedo llegar a echo " end end "
.
Otros consejos
Esto ordenará que el script se elimine a sí mismo y luego salga. El intérprete de comandos lee toda la línea antes de que se ejecute la línea, por lo que el comando de salida se ejecutará después del comando de eliminación aunque el archivo ya no exista.
del /f/q "%~0" | exit
Alternativamente, puede usar paréntesis si desea ejecutar muchos comandos después de que el archivo se haya eliminado ya que el intérprete de comandos leerá todo lo que está dentro de los paréntesis antes de ejecutarlo.
(del /f/q "%~0"
if exist "%~0" (echo.How did that happen?) else (echo.I've deleted myself.)
pause
exit)
¿Alguien sabe una manera de hacer que un .bat termine su ejecución incluso si se elimina mientras se ejecuta?
No creo que sea posible. Ejecución por lotes leída directamente del archivo. Si modifica el archivo, cambiará la ejecución (¡los programas por lotes auto modificables son maravillosamente difíciles de depurar!)
¿Por qué no comienzas tu archivo por lotes desde una ubicación diferente?
Incluso si no puede hacer eso, lo que puede hacer es tener un archivo que consta de una sola línea, llamando a otro archivo por lotes que no se elimina. Este archivo hace todo: inicia el programa Java, realiza toda la limpieza e incluso incluye la restauración del archivo por lotes original para que pueda ejecutarlo varias veces.
En lugar de ejecutar launch.bat a través de un cmd / c launch.bat
, que intentará transferir el control al archivo por lotes de llamada cuando esté listo, ejecútelo simplemente haciendo: launch.bat
Esto transferirá el control (piénselo como un goto en lugar de una llamada) al archivo por lotes, por lo que no intentará devolver el control a un archivo que ya no existe.
Es posible ejecutar líneas desde un archivo eliminado, pero las líneas deben residir en un bloque de paréntesis, ya que los bloques siempre se almacenan en caché completamente en la memoria antes de ejecutarse.
Obviamente no puede llamar a funciones en el lote, pero es posible llamar a otros archivos por lotes y recuperar el control (en el bloque).
@echo off
(
echo Delete myself
del %~f0
call ..\second.bat
echo do some other stuff after second.bat
)
echo This line can't be reached anymore