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()
Я немного заржавел на своем 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.