Ist es CMD.EXE möglich, eine umgeleitete Ausgabedatei freizugeben, bevor alle Unterprozesse beendet werden?

Ist es CMD.EXE möglich, eine umgeleitete Ausgabedatei freizugeben, bevor alle Unterprozesse beendet werden?

Ich habe ein Programm, das andere Instanzen von sich selbst startet. Jede Instanz leitet den Standardausgabestrom in eine andere Datei um. Ich habe ein Problem mit der folgenden Ereigniskette:

  1. Es wird eine BAT-Datei ausgeführt, die den Befehl enthältmy_program.exe > output_launcher.txt
  2. my_program.exe startet weitere Instanzen von sich selbst mit den Befehlen my_program.exe > output_1.txtundmy_program.exe > output_2.txt
  3. Die ursprüngliche Instanz ( my_program.exe > output_launcher.txt) wird beendet, während die beiden gestarteten Instanzen ( my_program.exe > output_1.txtund my_program.exe > output_2.txt) weiterhin ausgeführt werden.
  4. Die gleiche BAT-Datei von Nr. 1 wird erneut ausgeführt.
  5. Die neue Instanz my_program.exe > output_launcher.txtschlägt mit dem Fehler „Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird“ fehl.

Ich erhalte den Fehler nicht, wenn die BAT-Datei von Nr. 1 die Ausgabe nicht umleitet, und ich erhalte den Fehler nicht, wenn die beiden gestarteten Instanzen beendet werden, bevor die BAT-Datei ein zweites Mal ausgeführt wird.

Daher gehe ich davon aus, dass CMD.EXE die exklusiven Rechte an der Datei output_launcher.txt besitzt, bis alle Unterprozesse abgeschlossen sind.

Ist das zunächst einmal eine gute Annahme?

Ich möchte, dass CMD.EXE seine Rechte an output_launcher.txt aufgibt, wenn die ursprüngliche Instanz in Nr. 3 vorhanden ist, da jeder Unterprozess auf seine eigene Datei umleitet.

Ist dies möglich, wenn die Standardausgabe umgeleitet wird? Die beste Alternative, die mir einfällt, wäre, den Speicherort der Protokolldatei tatsächlich als Befehlszeilenargument zu verwenden und direkt aus meinem Programm in die Datei zu schreiben, anstatt die Standardausgabe umzuleiten. Dies würde jedoch viel mehr Arbeit für mich bedeuten, daher möchte ich diesen Weg nach Möglichkeit vermeiden.

Danke!

BEARBEITEN: Die eigentliche Befehlszeile, die die erste Instanz zum Starten der zusätzlichen Instanzen verwendet, sieht so aus start cmd /C "call my_program.exe > output_1.txt". Dann übergebe ich diesen Befehl an die Funktion „system()“ (my_program.exe ist in MSDN C geschrieben).

Vielleicht könnte ich die zusätzlichen Instanzen auf eine andere Weise starten, die helfen könnte?

Antwort1

Nach einigen kurzen Tests würde ich sagen, dass Ihre Annahme richtig zu sein scheint. Wenn Sie das überprüfen möchten, empfehle ichProzesshacker. (Oben gibt es eine Schaltfläche „Downloads“. Seien Sie vorsichtig, da die Anzeigen fehlerhafte Download-Links anzeigen.) Gehen Sie zu „Hacker“, „Handles oder DLLs suchen …“ (Strg+F).

Damit können Sie leicht überprüfen, was die Datei verwendet, und durch erneutes Ausführen der Suche feststellen, wann die Datei freigegeben wird.

Ich gehe davon aus, dass Process Explorer dies ähnlich machen könnte.

Beachten Sie, dass es für Sie möglicherweise besser ist, in einen eindeutigen Dateinamen zu schreiben. Bedenken Sie Folgendes: Anstatt output_1.txt beim ersten Unteraufruf und output_2.txt beim zweiten Unteraufruf zu verwenden, prüfen Sie, welche Dateien bereits vorhanden sind. Gehen Sie dann höher, damit Sie nicht am Ende eine Datei überschreiben oder auf Probleme stoßen, weil Sie nichts anhängen können, weil die Datei verwendet wird. Betriebssysteme und Programmiersprachen bieten häufig Funktionen zum Generieren eines eindeutigen Dateinamens.

Möglicherweise möchten Sie in viele temporäre Dateien schreiben und diese dann in weniger Dateien zusammenfassen. Ob diese Idee wirklich sinnvoll ist oder überhaupt nicht, hängt möglicherweise von Ihrem Projekt und Ihrer Herangehensweise ab.

Wenn Sie den Quellcode für program.exe haben, verwenden Sie statt „program.exe > Dateiname“ einfach „program.exe Dateiname“. Fügen Sie Code in Ihr Programm ein, um schnell in die Datei zu schreiben, und schließen Sie die Datei dann, damit sie nicht länger aufgehalten wird, wenn kein aktiver Schreibvorgang stattfindet. (Ein gründlicherer Prozess kann sogar eine „Sperre“ durchführen … da Sie mehrere Kopien des Programms ausführen, könnte sich die Investition in diese Funktion tatsächlich lohnen.) Verwenden Sie statt printf() eine benutzerdefinierte Funktion, die printf() nur aufruft, wenn keine Ausgabedatei angegeben ist, andernfalls schreibt sie in eine Datei. Anstatt dann jedes Mal, wenn Sie die Ausgabedatei ändern, alle Ihre printf()-Aufrufe ändern zu müssen, müssen Sie einfach den Wert einer Variablen ändern, die an Ihre benutzerdefinierte Ausgabefunktion übergeben wird. Ich weiß, Sie sagten, dies sei möglicherweise nicht vorzuziehen, da es etwas mehr Zeit in Anspruch nehmen würde. Ich möchte Sie jedoch wissen lassen, dass ich mir persönlich viel Zeit und Mühe gespart habe, nachdem ich diesen Ansatz entwickelt habe. Ich halte dies für eine gute langfristige Lösung.

Oder verwenden Sie die Protokollierungsfunktion des Betriebssystems. Dies kann durch Ausführen eines Befehls von der Befehlszeile aus erfolgen: Führen Sie unter Unix „logger“ aus; unter MS Windows führen Sie ausVeranstaltungErstellen. Es sollte Möglichkeiten geben, dies direkt aus der von Ihnen gewählten Programmiersprache heraus zu tun (MSDN C, wie Sie angemerkt haben). Das ist möglicherweise nicht ideal, wenn Ihre Ausgabe lang ist oder wenn Sie Bedenken haben, Ihre Betriebssystemprotokolle zu überladen. (Ich weiß, dass es an manchen Orten eine aktive Überwachung der Betriebssystemprotokolle gibt.)

Antwort2

Dies ist eine vernünftige Annahme.

1) Bitte stellen Sie sicher, dass die Datei nicht in einer anderen Anwendung geöffnet ist. Eine sinnvolle Möglichkeit hierfür wäre, zu versuchen, die Dateien umzubenennen, während die .bat-Anwendung nicht ausgeführt wird. Wenn dies fehlschlägt, hält eine andere Anwendung die Datei geöffnet.

2) Können Sie >>stattdessen versuchen, den Append-Operator zu verwenden >und mir sagen, was passiert?

verwandte Informationen