Laden...

Interop: Word Dokument feuert Close-Event nicht

Erstellt von JunkyXL vor 13 Jahren Letzter Beitrag vor 13 Jahren 4.074 Views
JunkyXL Themenstarter:in
1.665 Beiträge seit 2006
vor 13 Jahren
Interop: Word Dokument feuert Close-Event nicht

Hallo zusammen,

mit den Interop Assemblies möchte ich Word Dokumente steuern, sie öffnen und schließen. Ich muss jedoch auch mitbekommen, wann der User das Dokument schließt. Es wird jedoch kein einziges Close Event gefeuert, bis auf das DocumentBeforeClose Event, mit dem ich jedoch nichts anfangen kann, da der Zeitpunkt zu früh ist.

Wäre nett, wenn jemand drüberschauen könnte.
Testprojekt ist angehängt.

3.728 Beiträge seit 2005
vor 13 Jahren
Member-Variablen

Hallo JunkyXL,

die Events werden nicht gefeuert, da die COM-Wrapper-Objekte von denen diese Events gefeuert werden, ihren Gültigkeitsbereich längst verlassen haben.

Um den Problem zu beheben solltest Du folgendes tun:*Das var weglassen und stattdessen mit den eindeutigen COM-Interfaces bzw. Klassen arbeiten *Die Objektvariable document als klassenweit als Feld anlegen (Damit dauerhaft ein Verweis auf das Word-Dokument erhalten bleibt *Beim Dispose Marshal.ReleaseComObject für die Variable document aufrufen

Außerdem solltest Du generell keine Ketten bilden!! Das hat bei COM-Interop unangenehme Seiteneffekte. Diese Zeile solltest Du ändern:


// So nicht!
var document = app.Documents.Open( .... );

Besser ist folgender Ansatz:


// Sondern besser so:
Documents documents=app.Documents;
DocumentCalss document = documents.Open( .... );
Marshal.ReleaseComObject(documents);

JunkyXL Themenstarter:in
1.665 Beiträge seit 2006
vor 13 Jahren

Danke für die Antwort.

Das 'var' war nur auf die Schnelle für das Beispielprojekt. Habe das jetzt alles entsprechend angepasst, aber es wird immer noch nur das DocumentBeforeClose Event geschmissen.

PS: Ich habe ja die ApplicationClass als lokale Variable. Habe ich damit nicht automatisch bestehende Referenzen auf alle Dokumente solange Word und die Word-Klasse lebt?

Edit: Angepasstes Projekt hochgeladen

61 Beiträge seit 2009
vor 13 Jahren

Hallo JunkyXL,

bisher hatte ich das Close-Event gar nicht gefunden.
Es ist gut möglich, dass es nicht aufgerufen wird, weil es veraltet ist.
Ich habe mal etwas programmiert, dass die Dateien NACH dem Schließen verschlüsseln soll. Gelöst habe ich das jedoch im DocumentBeforeClose-Event.

Und noch etwas:
Das DocumentBeforClose-Event wird von der Application ausgelöst - vielleicht ist das bei dem Close-Event auch so.
Denn selbst wenn das Event im Document-Objekt ist, kann es dennoch von einem anderen Ort ausgelöst werden bzw. einen anderen Auslöser haben. Dass wäre bei den PIAs möglich, denn bei mir scheinen die unberechenbar ^^.

Hier der Ausschnitt mit dem DocumentBeforeClose-Event:



        /// <summary>
        /// Tritt ein, sobald man ein Dokument schließen möchte - also noch vor dem Speichern.
        /// z.B. durch Klicken auf [X] am Fenster
        /// </summary>
        /// <param name="Doc">Enthält das Dokument, das geschlossen werden soll.</param>
        private void Application_DocumentBeforeClose(Microsoft.Office.Interop.Word.Document Doc, ref bool Cancel)
        {
            if (Doc.Name.ToLower() == "Normal.dot".ToLower())
                return;

            try
            {
                // If-Abfrage
                //    Diese Abfrage prüft, ein Dokument Änderungen aufweist, die noch nicht gespeichert sind.
                //    Ist dies der Fall, wird eine definierte MessageBox aufgerufen und die Eingabe verarbeitet.
                //    >>>  Warum diese Abfrage?
                //    >>>>    Sinn dieser Abfrage ist es zu ermitteln,
                //    >>>>    ob beim Schließen der Speichervorgang abgebrochen wird (z.B. durch Klicken auf Abbrechen).
                if (!Doc.Saved)
                {
                    // Achtung: Diese Methode gibt nur TRUE zurück, wenn man abbrechen will
                    if(DokumentGespeichert(Doc, ref Cancel))
                        return;
                }

                string docFilePath = Path.Combine(Doc.Path, Doc.Name);
                Cancel = true;          

                object SaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
                object OrginalFormat = Word.WdOriginalFormat.wdOriginalDocumentFormat;
                Doc.Close(ref SaveChanges, ref OrginalFormat, ref missing);

                // das Document befindet sich am docFilePath und hier sind wir nach dem Close
                // this.DocumentAfterClose(Doc, ref Cancel); wenn man will
            }
            catch (Exception ex)
            {                
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Kann verwendet werden um zu erfragen, ob ein Dokument, dass nicht gespeichert wurde,
        /// gespeichert werden soll.
        /// </summary>
        /// <returns></returns>
        private bool DokumentGespeichert(Microsoft.Office.Interop.Word.Document Doc, ref bool Cancel)
        {
            // MessageBox
            //    Diese MessageBox stellt die Buttons zu verfügung, wie man sie bei der Frage,
            //    zum speichern eines Dokuments bei Word kennt.
            DialogResult result = MessageBox.Show("Möchten Sie die Änderungen in " + Doc.Name + " speichern?",
                                                  "Microsoft Office Word",
                                                  MessageBoxButtons.YesNoCancel,
                                                  MessageBoxIcon.Warning,
                                                  MessageBoxDefaultButton.Button2);

            // Auswerten des Ergenisses der DialogBox bzw. MessageBox
            switch (result)
            {
                case DialogResult.Cancel:
                    Cancel = true;
                    return true;
                case DialogResult.No:
                    break;
                case DialogResult.Yes:
                    Doc.Save();
                    Doc.Saved = true;
                    break;
                default:
                    break;
            }

            return false;
        }

Was hier passiert dürfte klar sein: Beim BeforeClose-Event wird das Speichern verarbeitet und das Dokument geschlossen. Anschließend ist man aber dennoch in der Methode und man kann so alles nach dem Schließen verarbeiten.

In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.