web-dev-qa-db-fra.com

Pourquoi Microsoft.Office.Interop.Excel.Application.Quit () laisse-t-il le processus en arrière-plan en cours d'exécution?

Le code suivant laisse un processus d'arrière-plan Microsoft Excel en cours d'exécution jusqu'à la fin de mon programme:

var excelApplication = new Application();
var workbooks = excelApplication.Workbooks;
var workbook = excelApplication.Workbooks.Open(file.FullName);

workbook.Close();
excelApplication.Workbooks.Close();
excelApplication.Quit();

Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApplication);

Pourquoi? Qu'est-ce que je rate?

11
skinnysoftware

Je l'ai!

application.Workbooks! = application.Workbooks

Cette propriété n'expose pas une variable, elle génère une valeur. Ainsi, chaque fois que j'accède à la propriété Workbooks, je crée un nouvel objet COM.

J'ai corrigé le code et tout va bien. Merci à tous.

var excelApplication = new Application();
var workbooks = excelApplication.Workbooks;
var workbook = workbooks.Open(pathToExcelWorkbook); // Fixed

workbook.Close();
workbooks.Close();
excelApplication.Quit();

Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApplication);
24
skinnysoftware

Il s'agit d'un problème répandu avec les applications Office. Tous les compléments/applications d'automatisation Excel doivent systématiquement publier leurs références aux objets Excel lorsqu'ils ne sont plus nécessaires. Ne pas libérer systématiquement les références aux objets Excel peut empêcher Microsoft Office Excel de s'arrêter correctement. Voir Libération systématique des objets pour plus d'informations. Il est lié à Outlook, mais les mêmes principes peuvent être appliqués à toutes les applications Office.

Utilisez System.Runtime.InteropServices.Marshal.ReleaseComObject pour libérer un objet Excel lorsque vous avez fini de l'utiliser. Définissez ensuite une variable sur Nothing dans Visual Basic (null en C #) pour libérer la référence à l'objet.

6
Eugene Astafiev

This IS MAUVAIS MANIEMENT DE FAIRE SIMILAIRE , mais c'est le moyen le plus facile de résoudre le problème :

    [DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    private Application _excelApp;
    private Workbook _excelWorkBook;
    private Worksheet _excelSheet;

    private void CloseExcelApp()
    {
        int hWnd = _excelApp.Application.Hwnd;
        uint processID;

        GetWindowThreadProcessId((IntPtr)hWnd, out processID);
        Process.GetProcessById((int)processID).Kill();

        _excelWorkBook = null;
        _excelApp = null;
        _excelSheet = null;
    }

tout ce dont vous avez besoin est d'initialiser toutes les variables non initialisées lorsque vous devez les utiliser et d'appeler CloseExcelApp () lorsque vous devez fermer l'application.

2
Andrew