In our C# WinForms application, we generate PDF files and launch Adobe Reader (or whatever the default system .pdf handler is) via the Process class. Since our PDF files can be large (approx 200K), we handle the Exited event to then clean up the temp file afterwards.
The system works as required when a file is opened and then closed again. However, when a second file is opened (before closing Adobe Reader) the second process immediately exits (since Reader is now using it's MDI powers) and in our Exited handler our File.Delete call should fail because it's locked by the now joined Adobe process. However, in Reader we instead get:
There was an error opening this document. This file cannot be found.
The unusual thing is that if I put a debugger breakpoint before the file deletion and allow it to attempt (and fail) the deletion, then the system behaves as expected!
I'm positive that the file exists and fairly positive that all handles/file streams to the file are closed before starting the process.
We are launching with the following code:
// 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();
Note: We are using the _pdfProcessDictionary to store references to the Process objects so that they stay in scope so that Exited event can successfully be raised.
Our cleanup/exited event is:
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
}
}
Possible solutions:
Detect that the file is still open in another process
Detect that the second process hasn't really been fully exited and that the file is opened in the first process instead