Frage

In unserer C # WinForms-Anwendung, erzeugen wir PDF-Dateien und starten Sie den Adobe Reader (oder was auch immer der Standard-System PDF-Handler ist) über die Process Klasse. Da unsere PDF-Dateien können große (ca. 200K) sein, wir das Exited Ereignis behandeln, um dann anschließend die temporäre Datei zu bereinigen.

Das System arbeitet nach Bedarf, wenn eine Datei geöffnet und dann wieder geschlossen. Wenn jedoch eine zweite Datei (vor dem Schließen Adobe Reader), um den zweiten Prozess sofort Ausfahrten geöffnet und in unserem Exited Handler unseres File.Delete Anruf (seit Reader ist nun MDI Befugnisse) ausfallen sollte, weil es durch den nun verbunden Adobe Prozess gesperrt ist . Aber wir stattdessen in Reader bekommen:

Es ist ein Fehler, dieses Dokument zu öffnen. Diese Datei kann nicht gefunden werden.

Die ungewöhnliche daran ist, dass, wenn ich einen Debugger-Breakpoint vor dem Löschen von Dateien setzen und lassen Sie es versuchen (und gescheitert) die Löschung, dann verhält sich das System wie erwartet!

Ich bin sicher, dass die Datei vorhanden ist und ziemlich positiv, dass alle Handgriffe / Datei in die Datei Ströme geschlossen werden, bevor der Prozess gestartet wird.

Wir sind mit dem folgenden Code gestartet:

// 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();

. Hinweis: Wir verwenden den _pdfProcessDictionary zum Speichern von Verweisen auf die Prozessobjekte, so dass sie in ihrem Umfang bleiben, so dass Exited Ereignis erfolgreich erhöht werden kann

Unsere Bereinigung / verlassen Ereignis ist:

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
    }
}

Mögliche Lösungen:

  • erkennt, dass die Datei in einem anderen Prozess noch offen ist
  • erkennen, dass der zweite Prozess vollständig beendet nicht wirklich wurde und dass die Datei in dem ersten Prozess geöffnet wird stattdessen
War es hilfreich?

Lösung

I nur mit diesem ein paar Tagen behandelt vor.

Wenn es keine Instanz bereits geöffnet ist, wird das Dokument öffnet sich in einem neuen Instanz direkt an.

Wenn es eine Instanz bereits geöffnet ist, glaube ich, dass Instanz Spawns eine neue Instanz, die Sie eigentlich nicht in den Griff bekommen. Was passiert ist, kehrt die Steuerung zu Ihrer Funktion sofort, die dann geht und löscht die Datei, bevor die neue Instanz eine Chance, lesen Sie die Datei hatte -. Daher erscheint es nicht dort sein

I „gelöst“ dies nicht die Dateien sofort zu löschen, sondern die Pfade in einer Liste zu verfolgen, und dann alle von ihnen nuking wenn das Programm beendet (jedes Lösch wickelt in einem try / catch mit einem leeren catch-Block in Fall die Datei in der Zwischenzeit verschwunden ist).

Andere Tipps

Ich würde folgender Ansatz vorschlagen:

  1. Erstellen von Dateien in temporären Verzeichnis des Benutzers ( Path.GetTempPath ). Sie können einige Unterordner darunter erstellen.
  2. Versuchen Sie Dateien nur zu löschen, wenn letzte Instanz Prozess beendet wird (dh Sie müssen Anzahl von Prozessen rechnen, dass Sie ins Leben gerufen hatte, an der Ausfahrt, dekrementiert die Zählung und wenn es Null wird, versuchen, zu löschen (alle) Dateien, die sind öffnen bisher)
  3. Versuchen Sie, clean-up erstellt Unterordner (unter temp-Verzeichnis) beim Starten und die Anwendung zu beenden. Sie können auch für die regelmäßige Bereinigungs mit Timer versuchen.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top