processo di Adobe Reader non riesce quando si inizia seconda istanza
-
12-10-2019 - |
Domanda
Nella nostra applicazione # WinForms C, generiamo file PDF e di lancio di Adobe Reader (o qualunque sia il gestore .pdf sistema predefinito è) tramite la classe Process
. Dal momento che i nostri file PDF possono essere di grandi dimensioni (circa 200K), gestiamo l'evento Exited
per poi ripulire il file temporaneo in seguito.
Il sistema funziona come previsto quando si apre un file e poi richiuso. Tuttavia, quando si apre un secondo file (prima di chiudere Adobe Reader), il secondo processo immediatamente uscite (dal Reader è ora usando il suo potere MDI) e nel nostro gestore Exited
nostra chiamata File.Delete dovesse fallire perché è bloccato dal processo di Adobe ora uniti . Tuttavia, in Reader che invece otteniamo:
C'è stato un errore l'apertura di questo documento. Questo file non può essere trovato.
La cosa insolita è che se metto un punto di interruzione debugger prima che l'eliminazione dei file e consentire a tentare (e non riescono) la cancellazione, poi le si comporta di sistema come previsto!
Sono positivo che il file esista e abbastanza positivo che tutte le maniglie / file di flussi al file sono chiusi prima di avviare il processo.
Stiamo lanciando con il seguente codice:
// 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();
Nota:. Stiamo usando il _pdfProcessDictionary
per memorizzare i riferimenti al processo di oggetti in modo che rimangano nella portata in modo tale evento Exited può essere sollevato con successo
La nostra pulizia / evento terminato è:
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
}
}
Possibili soluzioni:
- Rileva che il file è ancora aperto in un altro processo
- Rileva che il secondo processo è in realtà non è completamente chiuso e che il file viene aperto nel primo processo, invece
Soluzione
I solo affrontato questo un paio di giorni fa.
Quando non v'è alcuna istanza aprire già, il documento si apre in una nuova istanza direttamente.
Quando c'è un'istanza già aperta, credo che genera esempio una nuova istanza, che in realtà non ottenere un handle. Quello che succede è il controllo ritorna alla funzione immediatamente, che poi va ed elimina il file prima che la nuova istanza ha avuto la possibilità di leggere il file -. Da qui sembra non esserci
I "risolto" questo non eliminando i file immediatamente, ma tenere traccia dei percorsi in un elenco, e poi bombardare tutti loro quando si chiude il programma (avvolgere ogni eliminazione in un try / catch con un blocco catch vuoto caso il file è scomparso nel frattempo).
Altri suggerimenti
Vorrei suggerire seguente approccio:
- Crea file nella directory temp dell'utente ( Path.GetTempPath ). È possibile creare un po 'di sottocartella sotto di esso.
- Tentativo di eliminare i file solo quando ultima istanza di processo viene terminato (cioè è necessario contare il numero di processi che si era lanciato, in uscita, diminuire il conteggio e quando diventa zero, tentare di eliminare i file (tutti) che sono aprire finora)
- Prova a sottocartella clean-up creato (nella directory temp) durante l'avvio e termina l'applicazione. Si può anche tentare di periodica timer di clean-up utilizzando.