Prüfen, ob Programm schon disposed wurde
Hallo Forum,
ich habe in VB.NET ein Programm geschrieben, welches Word startet und dort Daten ausliest. Obwohl ich die Variable, die auf die Word-Applikation verweist, am Ende auf Nothing setze und dispose, bleibt Word im Task-Manager als Prozess weiterhin aktiv. Ich habe dann versucht, das Fenster zu maximieren, damit der Nutzer es manuell schließen kann, aber dann bricht die Prozedur ab.
Word ist weiterhin offen, aber mein Programm hat die Verbindung verloren und kann nicht mehr mit Word interagieren.
Wie kann ich entweder Word sauber beenden oder prüfen, ob es im Task-Manager noch als Prozess läuft und diesen dann sauber beenden (d.h. ggf. mit Möglichkeit zum Speichern)?
Vielen Dank im voraus,
M. Born
ich habe in VB.NET ein Programm geschrieben, welches Word startet und dort Daten ausliest. Obwohl ich die Variable, die auf die Word-Applikation verweist, am Ende auf Nothing setze und dispose, bleibt Word im Task-Manager als Prozess weiterhin aktiv. Ich habe dann versucht, das Fenster zu maximieren, damit der Nutzer es manuell schließen kann, aber dann bricht die Prozedur ab.
Word ist weiterhin offen, aber mein Programm hat die Verbindung verloren und kann nicht mehr mit Word interagieren.
Wie kann ich entweder Word sauber beenden oder prüfen, ob es im Task-Manager noch als Prozess läuft und diesen dann sauber beenden (d.h. ggf. mit Möglichkeit zum Speichern)?
Vielen Dank im voraus,
M. Born
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 496325
Url: https://administrator.de/contentid/496325
Ausgedruckt am: 24.11.2024 um 14:11 Uhr
17 Kommentare
Neuester Kommentar
Zitat von @MarcoBorn:
Hallo Forum,
ich habe in VB.NET ein Programm geschrieben, welches Word startet und dort Daten ausliest. Obwohl ich die Variable, die auf die Word-Applikation verweist, am Ende auf Nothing setze und dispose, bleibt Word im Task-Manager als Prozess weiterhin aktiv. Ich habe dann versucht, das Fenster zu maximieren, damit der Nutzer es manuell schließen kann, aber dann bricht die Prozedur ab.
Word ist weiterhin offen, aber mein Programm hat die Verbindung verloren und kann nicht mehr mit Word interagieren.
Wie kann ich entweder Word sauber beenden oder prüfen, ob es im Task-Manager noch als Prozess läuft und diesen dann sauber beenden (d.h. ggf. mit Möglichkeit zum Speichern)?
Wird Word über ein COM-Object angesprochen?, für die gibt's Extra Behandlung:Hallo Forum,
ich habe in VB.NET ein Programm geschrieben, welches Word startet und dort Daten ausliest. Obwohl ich die Variable, die auf die Word-Applikation verweist, am Ende auf Nothing setze und dispose, bleibt Word im Task-Manager als Prozess weiterhin aktiv. Ich habe dann versucht, das Fenster zu maximieren, damit der Nutzer es manuell schließen kann, aber dann bricht die Prozedur ab.
Word ist weiterhin offen, aber mein Programm hat die Verbindung verloren und kann nicht mehr mit Word interagieren.
Wie kann ich entweder Word sauber beenden oder prüfen, ob es im Task-Manager noch als Prozess läuft und diesen dann sauber beenden (d.h. ggf. mit Möglichkeit zum Speichern)?
System.Runtime.InteropServices.Marshal.ReleaseComObject(DeinWordObject)
Und vorher am Ende immer ein Quit() auf das Word-Application Object absetzen damit Word "sanft" schließt und nicht einfach nur abgewürgt wird.
Hi,
Wie @140913 schon schreibt, muss man das Word-Programm schon explizit über Quit() schließen, weil es als eigenständiger Prozess gestartet wird.
E.
Zitat von @MarcoBorn:
Obwohl ich die Variable, die auf die Word-Applikation verweist, am Ende auf Nothing setze und dispose, bleibt Word im Task-Manager als Prozess weiterhin aktiv. Ich habe dann versucht, das Fenster zu maximieren, damit der Nutzer es manuell schließen kann, aber dann bricht die Prozedur ab.
Also das Word.Application Objekt hat meines Wissens keine Dispose-Methode. Weiterhin - für andere Objekte - muss man natürlich erst das Dispose aufrufen (sofern für diese Klasse verfügbar) und dann erst die Variable auf Nothing setzen.Obwohl ich die Variable, die auf die Word-Applikation verweist, am Ende auf Nothing setze und dispose, bleibt Word im Task-Manager als Prozess weiterhin aktiv. Ich habe dann versucht, das Fenster zu maximieren, damit der Nutzer es manuell schließen kann, aber dann bricht die Prozedur ab.
Wie @140913 schon schreibt, muss man das Word-Programm schon explizit über Quit() schließen, weil es als eigenständiger Prozess gestartet wird.
E.
Liest Du unsere Kommentare nicht?
Methode Quit() ausführen! Was sollen wir da noch schreiben?
Edit:
Natürlich bevor Du die Variable auf Nothing setzt, ist klar.
Methode Quit() ausführen! Was sollen wir da noch schreiben?
Edit:
Natürlich bevor Du die Variable auf Nothing setzt, ist klar.
Lesen ist schon schwer, stand oben schon in meinem ersten Kommentar.
https://docs.microsoft.com/de-de/office/vba/api/word.application.quit(me ...
https://docs.microsoft.com/de-de/office/vba/api/word.application.quit(me ...
ReleaseComObject bringt mir nur eine Fehlermeldung
Das ist auch nur mögich wenn Word als reines COM-Object erzeugt wurde, nicht mit managed classes.aber trotzdem ist Word selbst 30 Minuten nach dem Ende des Programms immer noch aktiv.
Dann wirst du noch andere Referenzen offen haben.Selbst der GC sollte zwischendurch mindestens einmal durchgelaufen sein.
Den mal testweise die Garbage Collection manuell aufrufen.
Nochmal:
Word läuft als eigener Prozess! Da nützt Dir also "Nothing" und "Garbage Collection" für das Beenden des Prozess überhaupt nichts, weil es sich nur auf die belegten Ressourcen innerhalb Deines Programms bezieht.
Wenn der Prozess nach dem Quit() immer noch läuft, dann bekommst Du im VB.Net doch sicher eine Ausnahme gefeuert, oder?
Word läuft als eigener Prozess! Da nützt Dir also "Nothing" und "Garbage Collection" für das Beenden des Prozess überhaupt nichts, weil es sich nur auf die belegten Ressourcen innerhalb Deines Programms bezieht.
Wenn der Prozess nach dem Quit() immer noch läuft, dann bekommst Du im VB.Net doch sicher eine Ausnahme gefeuert, oder?
.DisplayAlerts = Word.Enums.WdAlertLevel.wdAlertsNone
Dir ist aber schon klar das du damit sämtliche Meldungen auch nach dem Schließen von Word permanent deaktivierst?Das sollte man vor dem Schließen der Instanz wieder zurücksetzen.
Hallo,
dein Problem besteht nicht nur bei Word, sonder auch bei Excel.
Bei beiden arbeitet die Quit()-Methode nicht sauber. Man müsste jetzt über die Marshalling gehen, aber das nervt und ist aufwendig.
(Stichworte: System.Runtime.InteropServices.Marshal und System.Runtime.InteropServices.GCHandle)
Folgendes ist zwar nicht "schön", aber funktioniert und ist schnell und einfach.
Der Ansatz ist einfach den Prozess für die Office-Instanz zu killen.
Das hier sollte auch für Word nutzbar sein (ist für Excel):
dein Problem besteht nicht nur bei Word, sonder auch bei Excel.
Bei beiden arbeitet die Quit()-Methode nicht sauber. Man müsste jetzt über die Marshalling gehen, aber das nervt und ist aufwendig.
(Stichworte: System.Runtime.InteropServices.Marshal und System.Runtime.InteropServices.GCHandle)
Folgendes ist zwar nicht "schön", aber funktioniert und ist schnell und einfach.
Der Ansatz ist einfach den Prozess für die Office-Instanz zu killen.
Das hier sollte auch für Word nutzbar sein (ist für Excel):
'Um Instanz am ende "abzuschießen",
'da das Quit/Close nicht korrekt arbeitet
Public Property procProcessesBeforeStart As Diagnostics.Process()
Public Property procProcessesAfterStart As Diagnostics.Process()
Public Property procProcessId4Excel As Int64 = -1 'Um Instanz am ende "abzuschießen"
''' <summary>
''' Gibt die ProcessID der aktiven gerade erstellten Excel Instanz zurück
''' </summary>
''' <returns></returns>
Public Function GetExcelProcessID() As Int64
Dim _intID As Int64 = -1
procProcessId4Excel = -1
For Each _itemAfter As Process In procProcessesAfterStart
Dim _bolDrin As Boolean = False
For Each _itemBefore As Process In procProcessesBeforeStart
If _itemBefore.Id = _itemAfter.Id Then
_bolDrin = True
Else
_bolDrin = False
End If
Next
If _bolDrin Then
Continue For
Else
_intID = _itemAfter.Id
Exit For
End If
Next
Return _intID
End Function
''' <summary>
''' Killt diese Instanz von Excel endgültig aus dem Speicher
''' </summary>
Public Sub KillExcelThisInstanz(Optional _bolShowError As Boolean = False)
Try
If procProcessId4Excel >= 0 Then
Dim _procExcel As Process = Process.GetProcessById(procProcessId4Excel)
_procExcel.Kill()
End If
Catch ex As Exception
'hier Fehlerhandling
End Try
End Sub
Public Sub Beispiel()
procProcessesBeforeStart = Diagnostics.Process.GetProcessesByName("Excel") '<---- !!
Dim objXLApp As New Microsoft.Office.Interop.Excel.Application
Dim objXLSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim objXLRange As Microsoft.Office.Interop.Excel.Range
procProcessesAfterStart = Diagnostics.Process.GetProcessesByName("Excel") '<----- !!
procProcessId4Excel = GetExcelProcessID() '<--- ProzessID der aktuellen Instanz
objXLApp.Workbooks.Add("xxxxxxxx")
objXLApp.Visible = False
objXLApp.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlNormal
objXLSheet = objXLApp.Workbooks(1).Sheets(1)
objXLRange = objXLSheet.Range("C2")
objXLRange.Value = "blahblah"
If IO.File.Exists("xxxxxxx") Then IO.File.Delete("xxxxxxx")
objXLApp.Workbooks(1).SaveAs("xxxxxxxxxx", Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault)
objXLApp.Quit()
KillExcelThisInstanz() '<---- und heier wird diese Instanz wider gekillt
end sub