この C# WinForms アプリケーションでは、PDF ファイルを生成し、クラスを介して Adobe Reader (または既定のシステム .pdf ハンドラー) を起動しますProcess
。PDF ファイルは大きくなる可能性があるため (約 200K)、Exited
イベントを処理して、後で一時ファイルをクリーンアップします。
ファイルが開かれ、再び閉じられると、システムは必要に応じて機能します。ただし、2 番目のファイルが (Adobe Reader を閉じる前に) 開かれると、2 番目のプロセスはすぐに終了し (Reader が MDI 機能を使用しているため)、Exited
ハンドラーで File.Delete 呼び出しが失敗するはずです。これは、結合された Adobe プロセスによってロックされているためです。ただし、Reader では代わりに次のようになります。
このドキュメントを開くときにエラーが発生しました。このファイルが見つかりません。
異常なのは、ファイルを削除する前にデバッガーのブレークポイントを設定し、削除を試みる (そして失敗する) ことを許可すると、システムが期待どおりに動作することです!
ファイルが存在することは確かであり、プロセスを開始する前にファイルへのすべてのハンドル/ファイル ストリームが閉じられていることはかなり肯定的です。
次のコードで起動しています。
// Open the file for viewing/printing (if the default program supports it)
var pdfProcess = new Process();
pdfProcess.StartInfo.FileName = tempFileName;
if (pdfProcess.StartInfo.Verbs.Contains("open", StringComparer.InvariantCultureIgnoreCase))
{
var verb = pdfProcess.StartInfo.Verbs.First(v => v.Equals("open", StringComparison.InvariantCultureIgnoreCase));
pdfProcess.StartInfo.Verb = verb;
}
pdfProcess.StartInfo.Arguments = "/N"; // Specifies a new window will be used! (But not definitely...)
pdfProcess.SynchronizingObject = this;
pdfProcess.EnableRaisingEvents = true;
pdfProcess.Exited += new EventHandler(pdfProcess_Exited);
_pdfProcessDictionary.Add(pdfProcess, tempFileName);
pdfProcess.Start();
注: を使用し_pdfProcessDictionary
て Process オブジェクトへの参照を保存し、Exited イベントを正常に発生できるようにスコープ内にとどめます。
クリーンアップ/終了イベントは次のとおりです。
void pdfProcess_Exited(object sender, EventArgs e)
{
Debug.Assert(!InvokeRequired);
var p = sender as Process;
try
{
if (_pdfProcessDictionary.ContainsKey(p))
{
var tempFileName = _pdfProcessDictionary[p];
if (File.Exists(tempFileName)) // How else can I check if I can delete it!!??
{
// NOTE: Will fail if the Adobe Reader application instance has been re-used!
File.Delete(tempFileName);
_pdfProcessDictionary.Remove(p);
}
CleanOtherFiles(); // This function will clean up files for any other previously exited processes in our dictionary
}
}
catch (IOException ex)
{
// Just swallow it up, we will deal with trying to delete it at another point
}
}
可能な解決策:
- ファイルがまだ別のプロセスで開かれていることを検出する
- 2 番目のプロセスが実際には完全に終了しておらず、代わりに最初のプロセスでファイルが開かれていることを検出します。