すべてのサブプロセスが終了する前に、CMD.EXE がリダイレクトされた出力ファイルを解放することは可能ですか?

すべてのサブプロセスが終了する前に、CMD.EXE がリダイレクトされた出力ファイルを解放することは可能ですか?

自分自身の別のインスタンスを起動するプログラムがあります。各インスタンスは標準出力ストリームを別のファイルにリダイレクトします。次の一連のイベントで問題が発生しています。

  1. 次のコマンドを含むBATファイルが実行される。my_program.exe > output_launcher.txt
  2. my_program.exeは、コマンドを使用して自身のインスタンスをさらに起動しmy_program.exe > output_1.txtmy_program.exe > output_2.txt
  3. 元のインスタンス ( my_program.exe > output_launcher.txt) は終了しますが、起動された 2 つのインスタンス (my_program.exe > output_1.txtおよびmy_program.exe > output_2.txt) は実行を継続します。
  4. #1 と同じ BAT ファイルが再度実行されます。
  5. の新しいインスタンスは、my_program.exe > output_launcher.txt「プロセスは別のプロセスによって使用されているため、ファイルにアクセスできません」というエラーで失敗します。

#1 の BAT ファイルが出力をリダイレクトしない場合はエラーは発生しません。また、起動された 2 つのインスタンスが BAT ファイルを 2 回目に実行する前に終了した場合もエラーは発生しません。

したがって、すべてのサブプロセスが終了するまで、CMD.EXE が output_launcher.txt ファイルに対する排他的権限を保持していると想定しています。

まず第一に、それは良い仮定でしょうか?

私が望んでいるのは、各サブプロセスが独自のファイルにリダイレクトされるため、元のインスタンスが #3 に存在するときに、CMD.EXE が output_launcher.txt に対する権限を放棄することです。

標準出力をリダイレクトする場合、これは可能ですか? 私が考えられる最善の代替案は、標準出力をリダイレクトするのではなく、実際にログ ファイルの場所をコマンド ライン引数として受け取り、プログラムから直接ファイルに書き込むことです。ただし、これには多くの作業が必要になるため、可能であればその方法は避けたいと思います。

ありがとう!

編集: 最初のインスタンスが追加のインスタンスを開始するために使用する実際のコマンド ラインは次のようになりますstart cmd /C "call my_program.exe > output_1.txt"。次に、そのコマンドを "system()" 関数に渡します (my_program.exe は MSDN C で記述されています)。

おそらく、別の方法で追加のインスタンスを起動すれば役立つでしょうか?

答え1

簡単にテストしてみたところ、あなたの推測は正しいようです。それを検証したい場合は、プロセスハッカー(上部に「ダウンロード」ボタンがあります。広告には不正なダウンロード リンクが表示されるので注意してください。) Hacker、Find Handles or DLLs... (Ctrl-F) に移動します。

これを使用すると、ファイルを使用しているものを簡単に確認でき、検索を再実行することで、ファイルがいつリリースされたかを確認できます。

Process Explorer でも同様のことができると期待しています。

一意のファイル名に書き込む方がよい場合があることに注意してください。次の点を考慮してください。最初のサブコールで output_1.txt、2 番目のサブコールで output_2.txt を使用する代わりに、どのファイルがすでに存在しているかを確認します。次に、上位のサブコールを使用します。こうすることで、ファイルが使用中であるために追加できず、ファイルを上書きしたり問題が発生したりすることがなくなります。オペレーティング システムとプログラミング言語では、一意のファイル名を生成する機能が頻繁に提供されます。

多数の一時ファイルに書き込み、それらを少数のファイルに結合したい場合があります。このアイデアが理にかなっているか、まったく意味がないかは、プロジェクトとアプローチ方法によって異なります。

program.exe のソース コードがある場合は、「program.exe > ファイル名」を実行する代わりに、「program.exe ファイル名」を使用します。プログラムにコードを配置して、ファイルにすばやく書き込み、アクティブな書き込みがないときにファイルを閉じないようにします。(より徹底したプロセスでは、何らかの「ロック」を実行することもあります... プログラムの複数のコピーを実行しているため、実際に投資する価値があるかもしれません。) printf() を呼び出す代わりに、出力ファイルが指定されていない場合にのみ printf() を呼び出し、それ以外の場合はファイルに書き込むカスタム関数を使用します。その後、出力ファイルを変更するたびにすべての printf() 呼び出しを変更する代わりに、カスタム出力関数に渡される 1 つの変数の値を変更するだけで済みます。時間がかかるため、これは好ましくないかもしれないとおっしゃったことは承知しています。ただし、この方法を思いついてから、個人的には多くの時間と労力を節約できたことをお知らせします。これは長期的に見て良い解決策だと思います。

または、オペレーティングシステムのログ機能の使用を検討してください。これは、コマンドラインからコマンドを実行することで実行できます。Unixでは「logger」を実行します。MS Windowsでは、イベント作成選択したプログラミング言語 (ご指摘のとおり、MSDN C) から直接これを行う方法があるはずです。出力が長い場合や、OS ログが乱雑になることを懸念している場合は、これは理想的ではないかもしれません。(OS ログをアクティブに監視している場所があることは知っています。)

答え2

それは合理的な仮定です。

1) ファイルが他のアプリケーションで開かれていないことを確認してください。これを行う適切な方法は、.bat アプリケーションが実行されていないときにファイルの名前を変更することです。これが失敗した場合、他のアプリケーションがファイルを開いたままにしています。

>>2)の代わりに追加演算子を使用してみて>、何が起こるか教えてください。

関連情報