Nur bestimmte Excel-Prozesse killen?

  • VB.NET

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von m.ad.

    Nur bestimmte Excel-Prozesse killen?

    Hallo Experten,

    bisher bin ich immer irgendwie fündig geworden. Aber jetzt komm ich trotz aller Suche nicht mehr weiter. Zu meinem Problem:

    In meinem Programm lese ich per Button Daten aus einer Exceltabelle aus. Dazu erstelle ich mir ein Excel-Objekt, öffne die gewünschte Datei, lese die gewünschte Zelle aus und schließe Excel dann wieder:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim Datei As String = "datei.xls"
    3. Dim Tabelle As String = "Tabelle1"
    4. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    5. Dim EXCEL As Object = CreateObject("Excel.Application")
    6. EXCEL.Application.Workbooks.Open(Application.StartupPath & "\" & Datei)
    7. TextBox1.Text = EXCEL.Application.Sheets(Tabelle).Cells(1, 1).Value
    8. EXCEL.Quit()
    9. End Sub
    10. End Class


    Jedes mal, wenn ich nun den Button1 drücke, wird verständlicherweise ein neuer Prozess (Taskmanager) erstellt. Nun habe ich schon rausgefunden, dass ich Excel mit folgenden Code erfolgreich aus der Prozess-Liste verbannen kann.

    VB.NET-Quellcode

    1. Private Sub KillExcel()
    2. For Each prozess As Process In Process.GetProcessesByName("EXCEL")
    3. prozess.Kill()
    4. Next
    5. End Sub


    Das finde ich aus meiner Sicht allerdings nicht so elegant, da ich hier einfach pauschal alles kille. Ich habe schon viel rumpobiert und konnte z.B. über den Process.MainWindowTitle() einige Excelprozesse, die ich nicht killen möchte davon verschonen.

    Nun meine Wunschvorstellung zu der ich durch Suchen und Probieren einfach nicht fündig werde:
    Da ich ja mit

    VB.NET-Quellcode

    1. Dim EXCEL As Object = CreateObject("Excel.Application")
    einen neuen Prozess erstelle, muss dieser doch irgendwie eine Kennung bekommen, bzw. sollte ich ihm eine Kennung vergeben können. Nachdem ich meine Ein- und Ausgaben mit dem Objekt/Prozess getätigt habe und dieses/dieser nicht weiter benötigt wird, sollte es doch möglich sein, genau diesen Prozess aus der Liste aller Excelprozesse herausfiltern und killen zu können??!

    Über einen entscheidenden Tipp bzw. Beipielcode wäre ich sehr dankbar.
    Du musst die einzelnen Objekte (Variablen) entladen, die von deinem Programm erzeugt werden, wenn du Excel schließt, sonst entstehen diese leeren Zombieprozesse.

    VB.NET-Quellcode

    1. Dim excelpath As String
    2. excelpath = "Pfad zur Exceltabelle"
    3. Dim excel As New Microsoft.Office.Interop.Excel.Application
    4. Dim excelworkbooks = excel.Workbooks
    5. Dim excelworkbook = excelworkbooks.Open(path_matrix)
    6. Dim excelsheets = excelworkbook.Worksheets
    7. Dim excelsheet = excelsheets("Deine Tabelle, die du bearbeitest")
    8. 'Dein Programm ....
    9. excel.CutCopyMode = False 'Damit deaktivierst du die Frage nach Daten im Zwischenspeicher von Excel
    10. excelworkbook.Close(False) ' Schließen, ohne zu speichern (falls Speichern gewünscht ist, den zweiten Parameter auf True setzen
    11. excel.Quit() 'Excel beenden
    12. 'Excelobjekte freistellten
    13. For Each obj In New Object() {excel, excelworkbooks, excelworkbook, excelsheets, excelsheet}
    14. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
    15. Next
    Hi Broco,

    danke für Deine Antwort. Aber das hilft mir leider nicht weiter. Wie aus meinem Code ersichtlich sein müsste, benutze ich für das Excel-Objekt die späte Bindung.

    VB.NET-Quellcode

    1. Dim EXCEL As Object = CreateObject("Excel.Application")

    Mein Programm muss nämlich auch mit älteren Excel-Versionen laufen, als mit der, die ich auf meinem Rechner nutze...

    VB.NET-Quellcode

    1. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(EXCEL)

    habe ich auch schon probiert. Der Prozess bleibt aber in der Liste. Wenn ich den Code dann mehrmals ausführe, dann verschwindet irgendwann auf einmal ein ganzer Satz an Excel-Prozessen. Nach meinen Recherchen sammelt vermutlich der Garbage Collector alle beendeten Prozesse ein.

    Bin ich evtl. einfach nur zu pedantisch, dass ich möchte, dass die Prozesse gleich verschwinden und nicht irgendwann, wenn der GC mal vorbeischneit?
    Du musst ALLE Objekte freigeben.
    EXCEL ist das CreateObject
    Dann kommt das Workbook, dann die Sheets und dann das eigentliche Worksheet.

    Also wäre eigentlich folgendes richtig:

    VB.NET-Quellcode

    1. EXCEL.Application.Sheets(Tabelle).Close(False)
    2. EXCEL.Application.Workbooks.Close(False)
    3. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(EXCEL.Application.Sheets(Tabelle)
    4. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(EXCEL.Application.Worksheets)
    5. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(EXCEL.Workbooks)
    6. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(EXCEL.Application)
    OK, also ich weiß nicht genau auf welchen Code Du Dich grade beziehst. Schon

    VB.NET-Quellcode

    1. Dim excel As New Microsoft.Office.Interop.Excel.Application
    kommt gar nicht in meinem Code vor, weil ich nicht auf meine Excelversion "verweise" sondern, das ganze mit

    VB.NET-Quellcode

    1. Dim EXCEL As Object = CreateObject("Excel.Application")
    (Späte Bindung) mache. In diesem meinen Code erstelle ich ja mit EXCEL ja nur EIN Objekt, was ich am Ende durch

    VB.NET-Quellcode

    1. System.Runtime.InteropServices.Marshal.FinalReleaseComObject(EXCEL)
    wieder freigebe. Wozu also noch das Workbook und die Sheets freigeben, wenn dafür gar kein Objekt existiert? Wie auch immer ich mache das jetzt so:

    VB.NET-Quellcode

    1. For Each prozess As Process In Process.GetProcessesByName("EXCEL")
    2. If prozess.MainWindowHandle = 0 Then prozess.Kill()
    3. Next

    Ich suche mir jetzt alle EXCEL-Prozesse raus, die kein MainWindow haben, also demnach meine Hintergrundprozesse sind und kille sie einfach. Läuft auch so. Ich hätte es zwar gerne etwas eleganter gehabt, aber geht schon.