none
Отцепить процесс Excel от программы на VB. RRS feed

  • Вопрос

  • Есть программа на VB, которая открывает Excel и создает отчет. После этого пользователь может закрыть программу, но Excel оставить открытым. Либо наоборот, увидел, например, ошибку в отчете, закрыл отчет и вернулся в программу, что бы исправить ошибку.
    Сейчас при закрытии программы даже отладчик не прекращает работать, пока не прервешь в ручную в VS. Так же при закрытии Excel процесс продолжает висеть в памяти. Если составлять несколько отчетов, то при каждом запуске появляется новый процесс. Как правильно разорвать связь между программой и Excel?

    Сейчас код такой

            Dim objExcel As New Excel.Application ' Excel
            Dim wbSmeta As Excel.Workbook ' книга сметы 
            Dim lstSm As Excel.Worksheet ' лист сметы
            ' создаем книгу
            wbSmeta = objExcel.Workbooks.Add()
            lstSm = wbSmeta.ActiveSheet
            lstSm.Activate()
            ' начальные установки
            objExcel.DisplayAlerts = False
            objExcel.ScreenUpdating = False
    
    << формируем отчет >>
    
            Try
                objExcel.Application.Visible = True
                objExcel.DisplayAlerts = True
                objExcel.ScreenUpdating = True
                lstSm.Cells.Columns.AutoFit()
    ' тут пытаюсь разорвать соединение с COM объектом
                Do While System.Runtime.InteropServices.Marshal.ReleaseComObject(objExcel) > 0
                Loop
                objExcel = Nothing
                wbSmeta = Nothing
                lstSm = Nothing
            Catch ex As Exception
                MsgBox(ex.Message)
            Finally
                GC.Collect()
            End Try
    

Ответы

Все ответы

  • Процесс Excel остаётся висеть в памяти, когда не все COM-объекты завершены.

    Нужно сохранять ссылки на все COM-объекты, чтобы потом их освободить. Пример.

    Также попробуйте использовать FinalReleaseComObject.

    • Помечено в качестве ответа Joiner-rus 27 мая 2017 г. 9:45
  • Просмотрел примеры. Стало более-менее понятно. Но остался открытым один вопрос - как вычислить все связанные COM - объекты. Удаление связей только с Excel, workbook и sheet результата не дало, ведь константы, линии бордюра, заливка ячеек - тоже COM объекты? Как узнать все связи.
  • когда надоест искать все висящие COM-объекты, сделайте как-то так (не знаю VB, думаю разберетесь как перевести):

    [DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    
    public static void ExcelKill(int hWnd)
    {
    	uint processID;
    	GetWindowThreadProcessId((IntPtr)hWnd, out processID);    
    	Process pr=Process.GetProcessById((int)processID);
    	pr.Kill();	
    }
    
    void WorkWithExcel()
    {
    	Application excel = new Application();
    	int hWnd = excel.Hwnd;
    	
    	//работа с Excel...
    	
    	ExcelKill(hWnd);
    }