¿Es posible que CMD.EXE libere un archivo de salida redirigido antes de que salgan todos los subprocesos?

¿Es posible que CMD.EXE libere un archivo de salida redirigido antes de que salgan todos los subprocesos?

Tengo un programa que lanza otras instancias de sí mismo. Cada instancia redirige el flujo de salida estándar a un archivo diferente. Tengo un problema con la siguiente cadena de eventos:

  1. Se ejecuta un archivo BAT que contiene el comandomy_program.exe > output_launcher.txt
  2. my_program.exe lanza más instancias de sí mismo usando los comandos my_program.exe > output_1.txtymy_program.exe > output_2.txt
  3. La instancia original ( my_program.exe > output_launcher.txt) sale mientras las dos instancias lanzadas ( my_program.exe > output_1.txty my_program.exe > output_2.txt) continúan ejecutándose.
  4. El mismo archivo BAT del n.º 1 se ejecuta nuevamente.
  5. La nueva instancia de my_program.exe > output_launcher.txtfalla con el error "El proceso no puede acceder al archivo porque está siendo utilizado por otro proceso".

No recibo el error si el archivo BAT del n.° 1 no redirige la salida, y no recibo el error si las dos instancias iniciadas salen antes de ejecutar el archivo BAT por segunda vez.

Entonces, supongo que CMD.EXE tiene derechos exclusivos sobre el archivo output_launcher.txt hasta que finalicen todos los subprocesos.

En primer lugar, ¿es una buena suposición?

Lo que me gustaría que sucediera es que CMD.EXE renuncie a sus derechos sobre output_launcher.txt cuando la instancia original exista en el n.° 3, ya que cada subproceso se redirige a su propio archivo.

¿Es esto posible al redirigir la salida estándar? La mejor alternativa que se me ocurre sería tomar la ubicación del archivo de registro como argumento de la línea de comando y escribir en el archivo directamente desde mi programa, en lugar de redirigir la salida estándar. Sin embargo, esto implicaría mucho más trabajo para mí, por lo que me gustaría evitar esa ruta si es posible.

¡Gracias!

EDITAR: La línea de comando real que usa la primera instancia para iniciar las instancias adicionales se ve así start cmd /C "call my_program.exe > output_1.txt". Luego paso ese comando a la función "system()" (my_program.exe está escrito en MSDN C).

¿Quizás podría iniciar las instancias adicionales de una manera diferente que podría ayudar?

Respuesta1

Después de algunas breves pruebas, diría que su suposición parece ser correcta. Si quieres comprobarlo te recomiendoHacker de procesos. (Hay un botón "Descargas" en la parte superior; tenga cuidado ya que los anuncios muestran enlaces de descarga incorrectos). Vaya a Hacker, Buscar identificadores o DLL... (Ctrl-F)

Al usarlo, puede verificar fácilmente qué está usando el archivo y, al volver a realizar la búsqueda, puede verificar cuándo se publica el archivo.

Espero que Process Explorer también pueda hacer esto de manera similar.

Tenga en cuenta que es mejor que escriba en un nombre de archivo único... considere esto: en lugar de salida_1.txt la primera subllamada y salida_2.txt la segunda subllamada, verifique qué archivos preexisten. Luego vaya más arriba, para no terminar sobrescribiendo un archivo o teniendo problemas porque no puede agregarlo porque el archivo está en uso. Los sistemas operativos y los lenguajes de programación suelen proporcionar funciones para generar un nombre de archivo único.

Es posible que desee escribir en muchos archivos temporales y luego combinarlos en menos archivos. Si esa idea tiene mucho sentido o ninguno, puede depender de su proyecto y de cómo aborde las cosas.

Si tiene el código fuente de program.exe, en lugar de ejecutar "program.exe > nombre de archivo", simplemente use "nombre de archivo programa.exe". Coloque código en su programa para escribir en el archivo rápidamente y luego cierre el archivo para que ya no se retenga cuando no haya una escritura activa. (Un proceso más completo puede incluso realizar algún "bloqueo"... dado que está ejecutando varias copias del programa, en realidad podría valer la pena invertir en eso). En lugar de llamar a printf(), use una función personalizada que solo llame a printf () si no se especifica ningún archivo de salida; de lo contrario, escribe en un archivo. Luego, en lugar de necesitar cambiar todas sus llamadas printf() cada vez que cambia el archivo de salida, simplemente necesita cambiar el valor de una variable que se pasa a su función de salida personalizada. Sé que dijiste que esto podría no ser preferible debido a que necesitas tomarte más tiempo. Sin embargo, le haré saber que personalmente me he ahorrado mucho tiempo y esfuerzo después de que se me ocurrió ese enfoque. Considero que ésta es una buena solución a largo plazo.

O considere utilizar la función de registro del sistema operativo. Esto se puede hacer ejecutando un comando desde la línea de comando: En Unix, ejecute "logger"; en MS Windows, ejecuteCrear evento. Debería haber formas de hacerlo directamente desde el lenguaje de programación que elija (MSDN C, como señaló). Esto podría no ser ideal si su salida es larga o si le preocupa saturar los registros de su sistema operativo. (Sé que algunos lugares tienen un monitoreo activo de los registros del sistema operativo).

Respuesta2

Es una suposición razonable.

1) Verifique que el archivo no esté abierto en ninguna otra aplicación. Una forma razonable de hacerlo sería intentar cambiar el nombre de los archivos mientras la aplicación .bat no se está ejecutando. Si esto falla, alguna otra aplicación mantiene el archivo abierto.

2) ¿Puedes intentar usar el Operador Agregar >>en lugar de >y decirme qué sucede?

información relacionada