Excel все еще работает после закрытия приложения vb.net

У меня проблемы с закрытием файлов Excel. Я делаю программу, которая открывает некоторые файлы Excel, использует информацию, а затем закрывает их.
Я пробовал несколько разных кодов, но они не работали, потому что EXCEL процесс все еще выполняется.

Мой первый код:

Dim aplicacaoexcel As New Excel.Application
Dim livroexcel As Object
Dim folhaexcel As Excel.Worksheet

livroexcel = aplicacaoexcel.Workbooks.Open("C:\Users\LPO1BRG\Desktop\Software Fiabilidade\Tecnicos.xlsx", UpdateLinks:=False, ReadOnly:=False, Password:="qmm7", WriteResPassword:="qmm7")
folhaexcel = livroexcel.sheets("Folha1")

aplicacaoexcel.DisplayAlerts = False
aplicacaoexcel.Visible = False
folhaexcel = Nothing
livroexcel.Close()
livroexcel = Nothing
aplicacaoexcel.Quit()
aplicacaoexcel = Nothing

Затем я добавил это: System.GC.Collect() но он все еще не закрывает процесс Excel.

Сейчас я пытаюсь это:

Dim process() As Process = system.Diagnostics.Process.GetProcessesByName("EXCEL")

For Each p As Process In process
   p.Kill()
Next

На самом деле, этот работает, но он закрывает все файлы Excel (даже те, которые не открываются моей программой).

Что я могу сделать, чтобы закрыть только файлы Excel, открытые моей программой?:)

4 ответа

Решение

Выпуская Excel.Application COM-объект Interop несколько сложнее, чем другие объекты Office Interop, поскольку некоторые объекты создаются без вашего ведома, и все они должны быть освобождены, прежде чем основное приложение может быть фактически закрыто.

Эти объекты включают в себя:

  • Excel.Application
  • Коллекция Excel.Application.WorkBooks
  • Коллекция WorkBooks открыла WorkBook
  • Коллекция WorkBook Sheets
  • Ссылка на коллекцию листов

Все эти объекты должны быть освобождены, чтобы завершить процесс EXCEL.

Простым решением является использование явных объявлений / назначений для всех объектов COM:

Dim ExcelApplication As New Microsoft.Office.Interop.Excel.Application()
Dim ExcelWorkbooks As Workbooks = ExcelApplication.Workbooks
Dim MyWorkbook As Workbook = ExcelWorkbooks.Open("[WorkBookPath]", False)
Dim worksheets As Sheets = MyWorkbook.Worksheets
Dim MyWorksheet As Worksheet = CType(worksheets("Sheet1"), Worksheet)

Когда вы закончите, отпустите их всех:

Imports System.Runtime.InteropServices

Marshal.ReleaseComObject(MyWorksheet)
Marshal.ReleaseComObject(worksheets)

MyWorkbook.Close(False)   '<= False if you don't want to save it!
Marshal.ReleaseComObject(MyWorkbook)

ExcelWorkbooks.Close()
Marshal.ReleaseComObject(ExcelWorkbooks)

ExcelApplication.Quit()
Marshal.FinalReleaseComObject(ExcelApplication)

Marshal.CleanupUnusedObjectsInCurrentContext()

Попробуйте что-то вроде workbook.Save, workbook.close

Я немного заржавел на своем VB и сейчас у меня нет доступа к Visual Studio, чтобы проверить это, но я попытаюсь написать код из памяти.

Проблема, с которой вы сталкиваетесь, состоит в том, что установка объекта равным Nothing по-прежнему оставляет объект, выделенный в памяти, и не удаляет объект полностью. Даже методы Close() и Quit() объекта по-прежнему оставляют его выделенным в памяти на случай, если программе понадобится доступ к ним позже. Метод Kill() работает, потому что он просто убивает приложение Excel, работающее в памяти, которое закрывает все открытые документы Excel, а также документы, используемые объектами COM. Что вы хотите сделать, так это избавиться от определенных COM-объектов, которые использует ваше приложение.

Попробуйте это изменение в вашем коде, хотя.

Dim aplicacaoexcel As New Excel.Application
Dim livroexcel As Object
Dim folhaexcel As Excel.Worksheet

livroexcel = aplicacaoexcel.Workbooks.Open("C:\Users\LPO1BRG\Desktop\Software Fiabilidade\Tecnicos.xlsx", UpdateLinks:=False, ReadOnly:=False, Password:="qmm7", WriteResPassword:="qmm7")
folhaexcel = livroexcel.sheets("Folha1")

aplicacaoexcel.DisplayAlerts = False
aplicacaoexcel.Visible = False

DisposeComObj(folhaexcel)
DisposeComObj(livroexcel)
DisposeComObj(aplicacaoexcel)

Затем добавьте следующее в ваше приложение.

Private Sub DisposeComObj(ByRef Reference As Object)
    Try        
        Do Until _
        System.Runtime.InteropServices.Marshal.ReleaseComObject(Reference)<=0
        Loop
    Catch
    Finally
        Reference = Nothing
    End Try
End Sub

Надеюсь, моя память хорошо мне служит. Я не писал никакого кода на VB или C# более года и чувствую себя очень не на практике. Я видел твой вопрос только потому, что нажал не на ту ссылку и вспомнил, как я боролся со сборкой мусора, когда начал программировать.

В начале процесса пропишите это:

      dim ExcellProcesses as string =""    
Dim startprocesses() As Process = system.Diagnostics.Process.GetProcessesByName("EXCEL")    

For Each sP As Process In startprocesses    
   ExcellProcesses = ExcellProcesses & ";" & sP.id() & ";"
Next

В конце процесса поставьте:

      Dim process() As EndProcesses = system.Diagnostics.Process.GetProcessesByName("EXCEL")

For Each eP As Process In Endprocesses
   if instr(ExcellProcesses,  ";" & eP.id() & ";")=0 then eP.kill
Next

таким образом будет уничтожен только вновь открытый процесс Excel.

Другие вопросы по тегам