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


3

他のインスタンスを起動するプログラムがあります。各インスタンスは、標準出力ストリームを異なるファイルにリダイレクトします。次の一連のイベントで問題があります。

  1. コマンドを含むBATファイルが実行されます my_program.exe > output_launcher.txt
  2. my_program.exeは、コマンドを使用して自分自身のインスタンスをさらに起動します。 my_program.exe > output_1.txt そして my_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ファイルが出力をリダイレクトしない場合はエラーにはなりません。また、BATファイルを2回実行する前に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で書かれています)。

追加のインスタンスを別の方法で起動できる可能性があります。


demo batとdemo exeのソースコードさえあれば、人々を助けるかもしれません。そしてstackoverflowは良いところで良いかもしれません、
barlop

回答:


1

少しのテストの後、私はあなたの仮定が正しいように思われると言うでしょう。それを確認したい場合は、お勧めします プロセスハッカー 。 (上部に[ダウンロード]ボタンがあります。広告にはダウンロードリンクが正しく表示されないため、注意してください。) ハッカー、ハンドルまたはDLLの検索...(Ctrl-F)

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

Process Explorerでも同様のことができると思います。

あなたがユニークなファイル名を書くことをお勧めするかもしれないことに注意してください。ファイルが使用中であるために追加できないため、ファイルを上書きしたり、問題にぶつかったりしないようにしてください。オペレーティングシステムやプログラミング言語は、固有のファイル名を生成する機能を提供しています。

あなたはたくさんの一時ファイルに書いて、それからもっと少ないファイルにそれらを結合したいかもしれません。その考えがまったく意味をなさない、あるいはまったく意味がないかどうかは、あなたのプロジェクトとあなたが物事にどう取り組むかにかかっているかもしれません。

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

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


詳細な回答いただきありがとうございます。 CMD.exeを使用して出力をリダイレクトするのではなく、ログファイルの場所を選択して私のプログラムから直接ファイルを開く/印刷する/閉じることをお勧めします。
BimmerM3

0

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

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

2)Append演算子を使ってみることができますか >> の代わりに > そして何が起こるのか教えて?


1)ファイルが他のアプリケーションで開かれていない。 2)Append演算子も同じ動作をします。
BimmerM3

私はメインの記事にもう少し役立つ情報を追加しました。
BimmerM3
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.