Process
在我们的 C# WinForms 应用程序中,我们生成 PDF 文件并通过该类启动 Adobe Reader(或任何默认系统 .pdf 处理程序) 。由于我们的 PDF 文件可能很大(大约 200K),我们处理该Exited
事件然后清理临时文件。
当文件被打开然后再次关闭时,系统会按要求工作。但是,当打开第二个文件时(在关闭 Adobe Reader 之前),第二个进程会立即退出(因为 Reader 现在正在使用它的 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
来存储对 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
}
}
可能的解决方案:
- 检测文件是否还在另一个进程中打开
- 检测到第二个进程还没有真正完全退出,而是在第一个进程中打开了文件