- PR -

ログファイルの作成方法について

1
投稿者投稿内容
shin2
ベテラン
会議室デビュー日: 2004/03/10
投稿数: 58
投稿日時: 2004-04-22 21:12
お世話になります。

現在アプリケーションにログファイル(テキスト形式)機能を加えています。
あるアプリケーション(ここではA)の開始時にログファイル(ここではログA)をオープンし、作業内容をログに書き込んでいきます。そしてある処理を”B"というアプリケーションで行っているとします。そこでアプリケーションBを立ち上げます。そのときログAにBの処理を書き込みたいのですが、なかなかうまくいきません。

単純にBを起動する直前にAの中でログAをクローズして、Bの中でログAをオープンさせるところまではうまくいくのですが、Bを終了して再びAの中でログAをオープンすることができません。例えば
(C#)
...
logA.Close();
//アプリケーションB起動
Process.Start("B.exe");
//作業終了再びログAを開く
StreamWriter log = File.AppendText("logA.txt"); ←ここでエラー!

いろいろ調べたのですが、テキスト形式でファイル共有でオープンできれば良いのですが、どのようにすればよいのかわかりません。
バイナリでは
FileStream fs = fileInfo.Open( FileMode, [ FileAccess ] , [ FileShare ] );
でファイル共有ができるのですが・・・ ちょっとしたことがわからず、投稿したしだいです。どなたか教えて下さい、よろしくお願いします。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-04-22 22:33
引用:

shin2さんの書き込み (2004-04-22 21:12) より:
バイナリでは
FileStream fs = fileInfo.Open( FileMode, [ FileAccess ] , [ FileShare ] );
でファイル共有ができるのですが・・・


微妙に問題がずれてる気がしないでもないですが、とりあえず上記のことに関しては、FileStreamとStreamWriterを組み合わせてできます。
StreamWriterのコンストラクタをよく調べて見てください。
shin2
ベテラン
会議室デビュー日: 2004/03/10
投稿数: 58
投稿日時: 2004-04-23 14:34
ありがとうございます。

とりあえずエラーは出なくなったのですが、どうもおかしい。 ちょっとしたことに見事にハマっていることだけはわかるのですが、原因がまだわかりません。

コード(C#)・・・余計なものはとりあえず省略
【アプリケーションA】
private void Form1_Load(object sender, System.EventArgs e)
{
  FileStream log2 = new FileStream("Log2004.txt",FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write);
  log = new StreamWriter(log2);
  log.WriteLine("アプリケーションA起動");
}

private void button1_Click(object sender, System.EventArgs e)
{
  log.WriteLine("アプリケーションBを起動します");
  Process.Start("LogPractice2.exe");
  log.WriteLine("アプリケーションAに戻りました");
}

private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
  log.WriteLine("アプリケーションAを終了します");
  log.Close();
}

【アプリケーションB・・・ファイル名:LogPractice2.exe】
private void PracForm2_Load(object sender, System.EventArgs e)
{
  FileStream log2 = new FileStream("Log2004.txt",FileMode.Append, FileAccess.Write, FileShare.Write);
  log = new StreamWriter(log2);
  log.WriteLine("***アプリケーションB起動***");
  log.Close();
}


これを実行してログファイルLog2004.txtを見ると
アプリケーションA起動
アプリケーションBを起動します
アプリケーションAに戻りました
アプリケーションAを終了します
***アプリケーションB起動***

・・・となってしまいます。アプリケーションBのログがまとまってアプリケーションA終了後のログとなって記述されてしまいます。本当はこうなって欲しいのです・・・
アプリケーションA起動
アプリケーションBを起動します
***アプリケーションB起動***
アプリケーションAに戻りました
アプリケーションAを終了します

何か(自分が)勘違いをしていると思います。長くなりましたが、わかる方がいらっしゃったら御指南よろしくお願いします。
PPN
会議室デビュー日: 2003/07/23
投稿数: 2
お住まい・勤務地: 横浜
投稿日時: 2004-04-23 16:00
はじめまして。

>private void button1_Click(object sender, System.EventArgs e)
>{
>  log.WriteLine("アプリケーションBを起動します");
>  Process.Start("LogPractice2.exe");
>  log.WriteLine("アプリケーションAに戻りました");
>}

の部分を

private void button1_Click(object sender, System.EventArgs e)
{
  log.WriteLine("アプリケーションBを起動します");
  Process wkProc = Process.Start("LogPractice2.exe");
wkProc.WaitForExit(); //プロセスの終了を待つ
  log.WriteLine("アプリケーションAに戻りました");
}

出よいのでわ。
shin2
ベテラン
会議室デビュー日: 2004/03/10
投稿数: 58
投稿日時: 2004-04-23 16:34
PPNさん、ありがとうございました。

一難去って・・・うまくいったつもりでしたが、アプリケーションBのログが全く書き込めなくなっています。ファイルのアクセス方法、共有方法そしてファイルのクローズの方法いずれかに問題があるのでしょうか? なお、前回のコードからPPNさんの指摘部分のみ変更したのみです

なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-04-23 16:45
引用:

shin2さんの書き込み (2004-04-23 16:34) より:
一難去って・・・うまくいったつもりでしたが、アプリケーションBのログが全く書き込めなくなっています。


冷静に考えて見ましょう。
ログ出力はStreamWriter→FileStreamで行われています。
これらはA,Bそれぞれのプログラムで独立です(当たり前)。

では、各FileStreamのカレントポジションはどうなりますか?
Bが書き込んだとき、Aのカレントポジションは変化しますか?
shin2
ベテラン
会議室デビュー日: 2004/03/10
投稿数: 58
投稿日時: 2004-04-23 16:54
引用:

冷静に考えて見ましょう。


・・・はい、すみません。 冷静に考えてみます。

引用:

では、各FileStreamのカレントポジションはどうなりますか?
Bが書き込んだとき、Aのカレントポジションは変化しますか?


Aのログファイルをクローズしないまま、Bが書き込むためAのカレントポジションは変化すると思います。私は単純に追記可のFileMode.Appendそして共有可のFileShare.WriteをAとB両方で設定しています。これが間違いなのでしょうか?
どうも昔やっていたVBの癖がここに出ているようです。すみませんがもう少し教えていただけないでしょうか??
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-04-23 19:15
引用:

shin2さんの書き込み (2004-04-23 16:54) より:
Aのログファイルをクローズしないまま、Bが書き込むためAのカレントポジションは変化すると思います。私は単純に追記可のFileMode.Appendそして共有可のFileShare.WriteをAとB両方で設定しています。これが間違いなのでしょうか?
どうも昔やっていたVBの癖がここに出ているようです。すみませんがもう少し教えていただけないでしょうか??


旧VBがどういう動作をするのかはよく知りません。また、Win32APIレベルでのファイルIOがどういう動作をするのかよく知らないので、APIレベルでの動作は分かりません。

.NET Framework のFileStreamでは、FileMode.Appendでファイルを開いた場合でも、必ず物理ファイルの最後(OSの共通ファイルキャッシュの最後?)に追加されるわけではなく、FileStreamの管理しているカレントポジションから追加されるようです。
※FileStream自体もバッファを持っているので、その絡みかもしれませんが。
 OSレベルで追記がどのように動作するのかは、上述したようによく知りません。

ですので、AとBで別々のFileStreamが動作している以上、それぞれのカレントポジションは同期されていないことになります。
また、それ以前にStreamWriter自体もバッファを持っているので、そちらのフラッシュタイミングにも依存したりしますね。

とりあえず、StreamWriterのフラッシュと、FileStreamでファイルの最終位置へのシークを適宜挿入してやることで回避はできたと思います。
1

スキルアップ/キャリアアップ(JOB@IT)