Bonjour à tous,

Je sais que certains ont des problèmes pour fermer complètement Excel, c’est à dire s’assurer qu’aucun processus Excel ne persiste dans le Task Manager. Je ne sais pas exactement à quoi c’est du, une histoire de framework compliquée, de destruction d’objet dans la mémoire bref…

Je vous donne une solution plutôt radicale qui consiste à tuer le procesus Excel. Le code est issu de quelques recherches sur des sites anglais principalement (je ne me souviens plus des sites) je l’ai simplement ordonné et épuré. Il y avait beaucoup d’autres sources avec de bonnes idées de solutions, mais celle-ci est la seule qui marche à chaque fois.

PRINCIPE:

Chaque processus a un ID, un numéro unique qui l’identifie. Lors de la création d’un processus Excel (donc lors du lancement de l’application), Windows lui affecte un ID. Il nous faut donc récupérer cet ID pour pouvoir par la suite le tuer (kill, lorsque l’on a terminé avec l’application Excel)

ETAPES:

1. Pour récupérer l’ID, on liste tous les processus EXCEL et on récupère (dans un tableau) leur ID respectif
2. On lance l’application Excel (oExcelApp = New Excel.Application etc.) et on liste de nouveau les IDs Excel. Nous avons donc récupéré dans cette nouvelle liste le nouvel ID correspondant à l’application Excel que nous venons de lancer.
3. Il nous reste à comparer les 2 listes pour récupérer l’ID du processus Excel que l’on vient de lancer.
4. Nous pourrons « killer » le processus par son ID lorsque nécessaire, sans toucher aux autres sessions Excel excitantes, c’est donc transparent pour l’utilisateur de votre programme.

Voilà, je vous avais prévenu, c’est radical mais c’est définitif, je l’ai testé sur plusieurs machines, avec frameworks 1.1, 2.0, 3.0, cela marche à chaque fois. J’espère en avoir aidé certains.

Greg

Imports Microsoft.Office.Interop

‘ Lancer Excel, ouvrir un fichier, fermer Excel :
Public Class Test
        Dim oExcelApp As New MSExcelApp
        ‘ Ouvre Excel en session invisible, et ouvre un fichier Excel
        With oExcelApp
            .Start(False)
            .OpenFile(« c:\fichier_excel.xls »)
            ‘ Faites ce que vous voulez ici
            ‘ Quitte Excel
            .Quit()
        End With
End Class

Public Class MSExcelApp
    Public Shared oExcelApp As Excel.Application
    Private intID As Int16

    Public Sub Start(ByVal blnVisible As Boolean)
        ‘ Lance Excel, l’application peut être visible ou non (blnVisible)
        ‘ Liste tous les procesus Excel en cours
        Dim intFirstIDs() As Int16 = MSExcelApp.ListID()

        ‘ Ouvre Excel
        oExcelApp = New Excel.Application
        oExcelApp.Visible = blnVisible

        ‘ Liste de nouveau tous les procesus Excel en cours, pour pouvoir comparer avec la première liste
        Dim intLastIDs() As Int16 = MSExcelApp.ListID()

        ‘ Extraction de l’ID grâce à la comparaison des 2 listes
        intID = MSExcelApp.ExtractID(intFirstIDs, intLastIDs)
    End Sub

    ‘ Ouvre un fichier Excel
    Public Sub OpenFile(ByVal strAbsolutePath As String)
        oExcelApp.Workbooks.Open(strAbsolutePath)
    End Sub

    ‘ Ferme Excel en tuant le procesus, nous devons lui fournir en paramètre l’ID récupéré lors de la création de la session Excel
    Public Sub Quit()
        Try
            Process.GetProcessById(intID).Kill()
        Catch ex As Exception
            MessageBox.Show(ex.Message & ex.StackTrace, « Error while closing Excel. », MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    ‘ Fonction qui liste les procesus
    Private Shared Function ListID() As Int16()
        ‘ Get the ID’s processes list in a array and sort it
        ‘ It is the only way to close Excel:
        ‘ To close Excel, we need to list the Excel ID’s processes  before user starts excel
        ‘ then we list them one more time just after opening Excel.
        ‘ We compare both of the lists we have to extract the new Excel ID of the brand new fucking Excel
        ‘ session.  So we can kill this process with the ID we got, without killing other Excel user
        ‘ session.
        ‘ L’explication ci-dessus résume l’explication générale de la méthode, cf présentation du code

        ‘ Get ID’s processes list
        Dim Processes As Process() = Nothing
        Processes = Process.GetProcessesByName(« EXCEL »)

        ‘ Load ID Processes in Array
        Dim intProcesses(Processes.GetUpperBound(0)) As Int16
        Dim i As Int16

        For i = 0 To Processes.GetUpperBound(0)
            intProcesses(i) = CInt(Processes(i).Id.ToString)
        Next
        Return intProcesses
    End Function

    ‘ Fonction qui compare les 2 listes de IDs, et nous renvoie l’ID voulu.
    Private Shared Function ExtractID(ByVal intFirstIDs As Int16(), ByVal intLastIDs As Int16()) As Int16
        Dim intID As Int16 = Nothing
        Dim intID_FirsList As Int16 = Nothing
        Dim intID_LastList As Int16 = Nothing
        Dim i As Int16 = Nothing

        For i = 0 To intLastIDs.GetUpperBound(0)
            intID_LastList = intLastIDs(i)
            If Array.IndexOf(intFirstIDs, intID_LastList) = -1 Then
                intID = intID_LastList
                Exit For
            End If
        Next
        Return intID
    End Function
End Class