Adobe Readerプロセスは、2番目のインスタンスを開始するときに失敗します
-
12-10-2019 - |
質問
C#Winformsアプリケーションでは、PDFファイルを生成し、Adobe Reader(またはデフォルトシステム.PDFハンドラーが何であれ)を起動します。 Process
クラス。 PDFファイルは大きくなる可能性があるため(約200k)、 Exited
その後、Tempファイルをクリーンアップするイベント。
ファイルが開いてから再び閉じたときに、システムは必要に応じて機能します。ただし、2番目のファイルを開くと(Adobe Readerを閉じる前に)、2番目のプロセスがすぐに終了します(読者は現在MDIパワーを使用しているため)。 Exited
file.delete通話は、現在結合されているAdobeプロセスによってロックされているため、故障する必要があります。ただし、読者では代わりに取得します。
このドキュメントを開くエラーがありました。このファイルは見つかりません。
珍しいことは、ファイルの削除の前にデバッガーのブレークポイントを配置し、削除を試みる(そして失敗する)ことを許可すると、システムが予想どおりに動作することです!
ファイルが存在することは肯定的であり、プロセスを開始する前にファイルへのすべてのハンドル/ファイルストリームが閉じられていることをかなり肯定しています。
次のコードで起動しています。
// 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
プロセスオブジェクトへの参照を保存して、それらがスコープにとどまり、排出されたイベントを正常に提起できるようにします。
私たちのクリーンアップ/出口イベントは次のとおりです。
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番目のプロセスが実際には完全に終了されていないこと、および代わりに最初のプロセスでファイルが開かれていることを検出します
解決
私 ただ 数日前にこれに対処しました。
インスタンスがまだ開いていない場合、ドキュメントは新しいインスタンスで直接開きます。
すでに開いているインスタンスがある場合、インスタンスは実際にハンドルを取得していない新しいインスタンスを生成すると思います。何が起こるかということは、コントロールがすぐにあなたの関数に戻り、その後、新しいインスタンスがファイルを読み取る機会がある前にファイルを削除します。したがって、そこにはないようです。
ファイルをすぐに削除するのではなく、リスト内のパスを追跡し、プログラムが終了したときにすべてのパスを追跡することでこれを「解決しました」その間に消えました)。
他のヒント
次のアプローチをお勧めします。
- ユーザーのTEMPディレクトリにファイルを作成します(path.getTemppath)。その下にサブフォルダーを作成できます。
- プロセスの最後のインスタンスが終了した場合にのみファイルを削除しようとします(つまり、出発し、出口でカウントを減らし、ゼロになったときに開いているファイルを削除しようとするプロセスの数をカウントする必要があります。 ))
- アプリケーションの開始と終了中に、作成されたサブフォルダー(TEMPディレクトリの下)をクリーンアップしてみてください。タイマーを使用して定期的なクリーンアップを試みることもできます。