Excel-Instazen bleiben nach Programmablauf bestehen

Klein0r

Erfahrenes Mitglied
Hallo,

wie der Titel schon sagt habe ich ein Problem mit diversen Excel-Instanzen. Ich öffne um die 50 Dateien und führe in jeder Datei ein Makro aus - danach wird die Datei sofort wieder geschlossen. Allerdings funktioniert die quit-Anweisung wohl nicht so richtig.

Code:
Code:
    Private Function executeMakro(ByVal file As FileInfo) As Boolean

        Dim oExcel As Excel.Application
        Dim oBook As Excel.Workbook
        Dim oBooks As Excel.Workbooks
        Dim retB As Boolean = True

        If file.Exists Then
            Try

                'Start Excel and open the workbook.
                oExcel = CType(CreateObject("Excel.Application"), Excel.Application)
                oExcel.Visible = False

                oBooks = oExcel.Workbooks
                oBook = CType(oBooks.Open(file.FullName), Excel.Workbook)

                'Run the macros.
                oExcel.Run("Tabelle1.CommandButton1_Click")

                'Clean-up: Close the workbook and quit Excel.
                oBook.Close(False)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook)
                oBook = Nothing

                System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks)
                oBooks = Nothing
                oExcel.Quit()

                System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel)
                oExcel = Nothing

            Catch ex As Exception
                retB = False
            End Try
        Else
            retB = False
        End If

        Return retB

    End Function

Das Thema wurde schon öfter in anderen Foren behandelt aber irgendwie gibts keine wirklich elegante Lösung für das Problem wie es mir scheint. Momentan habe ich es so gemacht:
http://www.ms-office-forum.net/forum/archive/index.php?t-156816.html

Also ich merke mir vor dem Durchlauf alle offenen Excel-Prozess-IDs und kille nachher nur die, die nicht in meiner Liste sind. Das funktioniert wohl - aber das ist ja nicht sonderlich elegant... Außerdem dauert die Ausführung ja eine weile und wenn der Benutzer zwischendurch Excel öffnen würde, würde diese PID nicht mit in der Liste stehen und mein Programm würde den Prozess gnadenlos beenden...

Falls ich nicht ins richtige Forum gepostet habe bitte ich einen Mod das Thema zu verschieben!

lg
 
Irgendwie geht es hier nicht so recht weiter mh.

Also auch im Forum habe ich nun schon einiges gefunden - aber keine richtige Antwort:
> http://www.tutorials.de/forum/net-datenverwaltung/258183-excel-prozess-endet-nicht.html
> http://www.tutorials.de/forum/net-application-und-service-design/235631-excel-richtig-beenden.html
> http://www.tutorials.de/forum/net-application-und-service-design/233509-document-open-syntax.html

Jetz finde ich immer wieder was zu ReleaseComObject - aber das nutze ich ja bereits...
http://addressof.com/blog/archive/2004/03/05/474.aspx

lg
 
Zuletzt bearbeitet:
Weiß wohl wirklich keiner Rat - deswegen nun eine andere Frage:

Was ist der Unterschied zwischen:
Code:
Me.oExcel = New Microsoft.Office.Interop.Excel.Application

Me.oExcel = New Microsoft.Office.Interop.Excel.ApplicationClass

Me.oExcel = CType(CreateObject("Excel.Application"), Excel.Application)

Me.oExcel = CType(CreateObject("Excel.Application"), Excel.ApplicationClass)

Läuft alles - aber ich bin mir nicht sicher ob es einen Unterschied macht.
Das komische ist auch das via IntelliSense die Klasse ApplicationClass garnicht angeboten wird. Sobald ich aber das ganze per Hand hinschreibe wird die Zeile nicht als Fehler gekennzeichnet und wird auch ohne Fehler ausgeführt.

Ich denke ich werde mir mal anschauen ob dort anderer ByteCode generiert wird.
 
Zuletzt bearbeitet:
Folgende Lösung:

Programmstart:
Code:
        Dim excelPIDs As New Generic.List(Of Integer)
        Dim excelProcessName As String = "excel"

        'Es werden alle Excel-Prozess-Ids gesammelt
        For Each prozess As System.Diagnostics.Process In Process.GetProcesses
            If prozess.ProcessName = excelProcessName OrElse prozess.ProcessName = excelProcessName.ToUpper Then
                excelPIDs.Add(prozess.Id)
            End If
        Next

        'Start Excel
        If Me.oExcel Is Nothing Then
            Me.oExcel = New Excel.Application
            Me.oExcel.Visible = False
        End If

        'Es werden alle Prozess-IDs gelöscht die vor dem Anwendungsstart schon
        'vorhanden waren und nicht vorhandene (neue) werden zur Liste hinzugefügt
        For Each prozess As System.Diagnostics.Process In Process.GetProcesses
            If prozess.ProcessName = excelProcessName OrElse prozess.ProcessName = excelProcessName.ToUpper Then
                If excelPIDs.Contains(prozess.Id) Then
                    excelPIDs.Remove(prozess.Id)
                Else
                    excelPIDs.Add(prozess.Id)
                End If
            End If
        Next

        'Falls genau eine PID übrig bleibt wird die ProzessID gespeichert
        'Falls mehrere existieren wurde gleichzeitig mit dem Programm
        'Excel gestartet und die PID konnte nicht eindeutig ermittelt werden
        If excelPIDs.Count = 1 Then
            Me.oExcelPID = excelPIDs(0)
        End If

Programmende:
Code:
        'Excel Beenden
        If Not Me.oExcel Is Nothing Then
            Me.oExcel.Quit()
            System.Runtime.InteropServices.Marshal.ReleaseComObject(Me.oExcel)
            Me.oExcel = Nothing
        End If

        If Me.oExcelPID <> -1 Then
            For Each prozess As System.Diagnostics.Process In Process.GetProcesses
                If prozess.Id = Me.oExcelPID Then
                    prozess.Kill()
                End If
            Next
        End If

Kommentare lesen für Erklärung und bei Fragen: fragen!

lg
 

Neue Beiträge

Zurück