L’applicazione non si chiude dopo aver chiamato quit

Ciao ragazzi, ho un piccolo problema che non riesco a capire. Sto salvando un DataGridView (è contenuto) in un file xls. Non ho alcun problema a farlo, tranne che nel mio task manager, sta ancora mostrando che è in esecuzione. Ho chiamato:

xlApp.Application.Quit() 

Questo è dichiarato come:

  Dim xlApp As New excel.Application 

Questo sembra non funzionare, MA questo è lo stesso modo in cui esco quando lascio che l’utente scelga di esportarlo in un documento di Word. Non sono sicuro di dove sto andando storto …

Ecco il mio codice completo

 Imports Word = Microsoft.Office.Interop.Word Imports Excel = Microsoft.Office.Interop.Excel Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For x As Integer = 1 To 3500 DataGridView1.Rows.Add(New Object() {"r" & x.ToString & "c1", "r" & x.ToString & "c2", "r" & x.ToString & "c3", "r" & x.ToString & "c4", "r" & x.ToString & "c5"}) Next End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click exportToWord (DataGridView1) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim xlApp As New Excel.Application Dim xlWorkBook As Excel.Workbook Dim xlWorkSheet As Excel.Worksheet 'Dim misValue As Object = System.Reflection.Missing.Value xlWorkBook = xlApp.Workbooks.Add xlWorkSheet = DirectCast(xlWorkBook.Sheets("sheet1"), Excel.Worksheet) xlApp.Visible = True Dim headers = (From ch In DataGridView1.Columns _ Let header = DirectCast(DirectCast(ch, DataGridViewColumn).HeaderCell, DataGridViewColumnHeaderCell) _ Select header.Value).ToArray() Dim headerText() As String = Array.ConvertAll(headers, Function(v) v.ToString) Dim items() = (From r In DataGridView1.Rows _ Let row = DirectCast(r, DataGridViewRow) _ Where Not row.IsNewRow _ Select (From cell In row.Cells _ Let c = DirectCast(cell, DataGridViewCell) _ Select c.Value).ToArray()).ToArray() Dim table As String = String.Join(vbTab, headerText) & Environment.NewLine For Each a In items Dim t() As String = Array.ConvertAll(a, Function(v) v.ToString) table &= String.Join(vbTab, t) & Environment.NewLine Next table = table.TrimEnd(CChar(Environment.NewLine)) Clipboard.SetText (table) Dim alphabet() As Char = "abcdefghijklmnopqrstuvwxyz".ToUpper.ToCharArray Dim range As excel.Range = xlWorkSheet.Range("B2:" & alphabet(headerText.Length) & (items.Length + 2).ToString) range.Select() xlWorkSheet.Paste() range.Borders(Excel.XlBordersIndex.xlDiagonalDown).LineStyle = Excel.XlLineStyle.xlLineStyleNone range.Borders(Excel.XlBordersIndex.xlDiagonalUp).LineStyle = Excel.XlLineStyle.xlLineStyleNone With range.Borders(Excel.XlBordersIndex.xlEdgeLeft) .LineStyle = Excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = Excel.XlBorderWeight.xlMedium End With With range.Borders(Excel.XlBordersIndex.xlEdgeTop) .LineStyle = Excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = Excel.XlBorderWeight.xlMedium End With With range.Borders(Excel.XlBordersIndex.xlEdgeBottom) .LineStyle = Excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = Excel.XlBorderWeight.xlMedium End With With range.Borders(Excel.XlBordersIndex.xlEdgeRight) .LineStyle = Excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = Excel.XlBorderWeight.xlMedium End With With range.Borders(Excel.XlBordersIndex.xlInsideVertical) .LineStyle = Excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = Excel.XlBorderWeight.xlThin End With With range.Borders(Excel.XlBordersIndex.xlInsideHorizontal) .LineStyle = Excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = Excel.XlBorderWeight.xlThin End With 'xlApp.Visible = True xlWorkBook.SaveAs("C:\Users\CoDeXeR\Desktop\Word1.xls", True) xlWorkBook.Close() xlApp.Application.Quit() ReleaseObject(xlWorkSheet) '<~~~ Added as per comment from deleted post ReleaseObject (xlWorkBook) ReleaseObject (xlApp) End Sub Public Sub exportToWord(ByVal dgv As DataGridView) ' Create Word Application Dim oWord As Word.Application = DirectCast(CreateObject("Word.Application"), Word.Application) ' Create new word document Dim oDoc As Word.Document = oWord.Documents.Add() Dim headers = (From ch In dgv.Columns _ Let header = DirectCast(DirectCast(ch, DataGridViewColumn).HeaderCell, DataGridViewColumnHeaderCell) _ Select header.Value).ToArray() Dim headerText() As String = Array.ConvertAll(headers, Function(v) v.ToString) Dim items() = (From r In dgv.Rows _ Let row = DirectCast(r, DataGridViewRow) _ Where Not row.IsNewRow _ Select (From cell In row.Cells _ Let c = DirectCast(cell, DataGridViewCell) _ Select c.Value).ToArray()).ToArray() Dim table As String = String.Join(vbTab, headerText) & Environment.NewLine For Each a In items Dim t() As String = Array.ConvertAll(a, Function(v) v.ToString) table &= String.Join(vbTab, t) & Environment.NewLine Next table = table.TrimEnd(CChar(Environment.NewLine)) Clipboard.SetText (table) Dim oTable As Word.Table = oDoc.Tables.Add(oDoc.Bookmarks.Item("\endofdoc").Range, items.Count + 1, headers.Count) oTable.Range.Paste() 'make the first row bold, fs 14 + change textcolor oTable.Rows.Item(1).range.Font.Bold = &H98967E oTable.Rows.Item(1).range.Font.Size = 14 oTable.Rows.Item(1).range.Font.Color = Word.WdColor.wdColorWhite 'change backcolor of first row oTable.Rows.Item(1).range.Shading.Texture = Word.WdTextureIndex.wdTextureNone oTable.Rows.Item(1).range.Shading.ForegroundPatternColor = Word.WdColor.wdColorAutomatic oTable.Rows.Item(1).range.Shading.BackgroundPatternColor = Word.WdColor.wdColorLightBlue ''set table borders 'With oTable.Range.Tables(1) ' With .Borders(Word.WdBorderType.wdBorderLeft) ' .LineStyle = Word.WdLineStyle.wdLineStyleSingle ' .LineWidth = Word.WdLineWidth.wdLineWidth100pt ' .Color = Word.WdColor.wdColorAutomatic ' End With ' With .Borders(Word.WdBorderType.wdBorderRight) ' .LineStyle = Word.WdLineStyle.wdLineStyleSingle ' .LineWidth = Word.WdLineWidth.wdLineWidth100pt ' .Color = Word.WdColor.wdColorAutomatic ' End With ' With .Borders(Word.WdBorderType.wdBorderTop) ' .LineStyle = Word.WdLineStyle.wdLineStyleSingle ' .LineWidth = Word.WdLineWidth.wdLineWidth100pt ' .Color = Word.WdColor.wdColorAutomatic ' End With ' With .Borders(Word.WdBorderType.wdBorderBottom) ' .LineStyle = Word.WdLineStyle.wdLineStyleSingle ' .LineWidth = Word.WdLineWidth.wdLineWidth100pt ' .Color = Word.WdColor.wdColorAutomatic ' End With ' With .Borders(Word.WdBorderType.wdBorderHorizontal) ' .LineStyle = Word.WdLineStyle.wdLineStyleSingle ' .LineWidth = Word.WdLineWidth.wdLineWidth050pt ' .Color = Word.WdColor.wdColorAutomatic ' End With ' With .Borders(Word.WdBorderType.wdBorderVertical) ' .LineStyle = Word.WdLineStyle.wdLineStyleSingle ' .LineWidth = Word.WdLineWidth.wdLineWidth050pt ' .Color = Word.WdColor.wdColorAutomatic ' End With ' .Borders(Word.WdBorderType.wdBorderDiagonalDown).LineStyle = Word.WdLineStyle.wdLineStyleNone ' .Borders(Word.WdBorderType.wdBorderDiagonalUp).LineStyle = Word.WdLineStyle.wdLineStyleNone ' .Borders.Shadow = False 'End With ' Save this word document oDoc.SaveAs("C:\Users\CoDeXeR\Desktop\Word1.doc", True) oDoc.Close() oWord.Application.Quit() 'oWord.Visible = True End Sub Public Sub exportToExcel(ByVal dgv As DataGridView) End Sub Private Sub ReleaseObject(ByVal obj As Object) Try System.Runtime.InteropServices.Marshal.ReleaseComObject (obj) obj = Nothing Catch ex As Exception obj = Nothing Finally GC.Collect() End Try End Sub End Class 

    Just Calling .Quit() non rimuoverà l’applicazione dalla memoria. È molto importante chiudere gli oggetti dopo aver terminato la codifica. Ciò garantisce che tutti gli oggetti vengano rilasciati correttamente e che nulla rimanga nella memoria.

    Vedi questo esempio

     Imports Excel = Microsoft.Office.Interop.Excel Public Class Form1 '~~> Define your Excel Objects Dim xlApp As New Excel.Application Dim xlWorkBook As Excel.Workbook Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click '~~> Add a New Workbook xlWorkBook = xlApp.Workbooks.Add '~~> Display Excel xlApp.Visible = True '~~> Do some stuff Here '~~> Save the file xlWorkBook.SaveAs(Filename:="C:\Tutorial\SampleNew.xlsx", FileFormat:=51) '~~> Close the File xlWorkBook.Close() '~~> Quit the Excel Application xlApp.Quit() '~~> Clean Up releaseObject (xlApp) releaseObject (xlWorkBook) End Sub '~~> Release the objects Private Sub releaseObject(ByVal obj As Object) Try System.Runtime.InteropServices.Marshal.ReleaseComObject (obj) obj = Nothing Catch ex As Exception obj = Nothing Finally GC.Collect() End Try End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Me.Close() End Sub End Class 

    Vale anche la pena menzionare la regola dei 2 DOT .

    Se ami automatizzare Excel da VB.Net, potresti anche dare un’occhiata a questo link .

    AZIONE SUPPLEMENTARE

    Il problema è la regola dei 2 DOT come ho menzionato sopra. Quando si utilizza la regola DOT 2 (Es: Excel.XlBordersIndex.xlDiagonalDown ), è necessario eseguire Garbage Collection utilizzando GC.Collect() . Quindi tutto ciò che devi fare è aggiungere questa parte

      Finally GC.Collect() 

    nel Private Sub ReleaseObject(ByVal obj As Object)

     Private Sub ReleaseObject(ByVal obj As Object) Try Dim intRel As Integer = 0 Do intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) Loop While intRel > 0 MsgBox("Final Released obj # " & intRel) Catch ex As Exception MsgBox("Error releasing object" & ex.ToString) obj = Nothing Finally GC.Collect() End Try End Sub 

    CODICE FINALE (provato e testato)

     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim xlApp As New excel.Application Dim xlWorkBook As excel.Workbook Dim xlWorkSheet As excel.Worksheet Dim xlRange As excel.Range 'Dim misValue As Object = System.Reflection.Missing.Value xlWorkBook = xlApp.Workbooks.Add xlWorkSheet = DirectCast(xlWorkBook.Sheets("sheet1"), excel.Worksheet) xlApp.Visible = True Dim headers = (From ch In DataGridView1.Columns _ Let header = DirectCast(DirectCast(ch, DataGridViewColumn).HeaderCell, DataGridViewColumnHeaderCell) _ Select header.Value).ToArray() Dim headerText() As String = Array.ConvertAll(headers, Function(v) v.ToString) Dim items() = (From r In DataGridView1.Rows _ Let row = DirectCast(r, DataGridViewRow) _ Where Not row.IsNewRow _ Select (From cell In row.Cells _ Let c = DirectCast(cell, DataGridViewCell) _ Select c.Value).ToArray()).ToArray() Dim table As String = String.Join(vbTab, headerText) & Environment.NewLine For Each a In items Dim t() As String = Array.ConvertAll(a, Function(v) v.ToString) table &= String.Join(vbTab, t) & Environment.NewLine Next table = table.TrimEnd(CChar(Environment.NewLine)) Clipboard.SetText(table) Dim alphabet() As Char = "abcdefghijklmnopqrstuvwxyz".ToUpper.ToCharArray xlRange = xlWorkSheet.Range("B2:" & alphabet(headerText.Length) & (items.Length + 2).ToString) xlRange.Select() xlWorkSheet.Paste() xlRange.Borders(excel.XlBordersIndex.xlDiagonalDown).LineStyle = excel.XlLineStyle.xlLineStyleNone xlRange.Borders(excel.XlBordersIndex.xlDiagonalUp).LineStyle = excel.XlLineStyle.xlLineStyleNone With xlRange.Borders(excel.XlBordersIndex.xlEdgeLeft) .LineStyle = excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = excel.XlBorderWeight.xlMedium End With With xlRange.Borders(excel.XlBordersIndex.xlEdgeTop) .LineStyle = excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = excel.XlBorderWeight.xlMedium End With With xlRange.Borders(excel.XlBordersIndex.xlEdgeBottom) .LineStyle = excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = excel.XlBorderWeight.xlMedium End With With xlRange.Borders(excel.XlBordersIndex.xlEdgeRight) .LineStyle = excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = excel.XlBorderWeight.xlMedium End With With xlRange.Borders(excel.XlBordersIndex.xlInsideVertical) .LineStyle = excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = excel.XlBorderWeight.xlThin End With With xlRange.Borders(excel.XlBordersIndex.xlInsideHorizontal) .LineStyle = excel.XlLineStyle.xlContinuous .ColorIndex = 1 'black .TintAndShade = 0 .Weight = excel.XlBorderWeight.xlThin End With xlWorkBook.SaveAs(Filename:="C:\Users\Siddharth Rout\Desktop\Word1.xls", FileFormat:=56) xlWorkBook.Close() xlApp.Quit() ReleaseObject(xlRange) ReleaseObject(xlWorkSheet) ReleaseObject(xlWorkBook) ReleaseObject(xlApp) End Sub Private Sub ReleaseObject(ByVal obj As Object) Try Dim intRel As Integer = 0 Do intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) Loop While intRel > 0 MsgBox("Final Released obj # " & intRel) Catch ex As Exception MsgBox("Error releasing object" & ex.ToString) obj = Nothing Finally GC.Collect() End Try End Sub 

    Nessuna delle raccomandazioni precedenti ha funzionato per me finché non ho seguito il commento di @ SiddharthRout sopra. ” Ad oggi, qual è il modo giusto per lavorare con gli oggetti COM? ”

    Indica che i riferimenti a oggetti COM sono mantenuti in vita sotto il debugger. Una soluzione è chiamare GC dalla procedura che chiama la procedura com. Ha funzionato per me.

    Esegui GC da Finally in un blocco TRY Catch.

    copiato da: post by "Govert" on what is the right way to work with COM objects?

     using System; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; namespace TestCsCom { Class Program { static void Main(string[] args) { // NOTE: Don't call Excel objects in here... // Debugger would keep alive until end, preventing GC cleanup // Call a separate function that talks to Excel DoTheWork(); // Now let the GC clean up (repeat, until no more) do { GC.Collect(); GC.WaitForPendingFinalizers(); } while (Marshal.AreComObjectsAvailableForCleanup()); } static void DoTheWork() { Application app = new Application(); Workbook book = app.Workbooks.Add(); Worksheet worksheet = book.Worksheets["Sheet1"]; app.Visible = true; for (int i = 1; i < = 10; i++) { worksheet.Cells.Range["A" + i].Value = "Hello"; } book.Save(); book.Close(); app.Quit(); // NOTE: No calls the Marshal.ReleaseComObject() are ever needed } } } 

    Ho usato la possibilità di chiudere un documento EXCEL nello script molte volte insieme a hide rendere visibile e ora chiudendo se è l’unica cartella di lavoro aperta altrimenti chiudi questo foglio di lavoro. Ecco il mio

     Sub ExitWorkBook() Dim wb As Workbook Dim c As Integer c = 0 For Each wb In Application.Workbooks c = c + 1 Next wb If c = 1 Then Application.Quit '--Quit this worksheet but keep excel open. Else Workbooks("(excel workbook name).xls").Close '-- Close Excel End If ' End Sub 

    For Each w In Application.Workbooks w.Save Next w Application.Quit

    http://msdn.microsoft.com/en-us/library/office/ff839269.aspx

    Ho avuto lo stesso problema. Tuttavia, il problema persisteva solo durante il debug. Tutto quello che dovresti fare è

     xlWorkBook.Close xlApp.Quit 

    Quindi lascia che il codice funzioni. Potrebbe essere necessario chiamare il Garbage Collector dopo che Button1_Click è finito, ma non ne avevo nemmeno bisogno. Sembra che passare il codice o non lasciare che finisca completamente getta le cose e lascia Excel aperto.

    Vedi il processo Excel non si chiude in VB.net

    Ho risolto il problema usando:

     Set xlApp = Nothing 

    È ansible controllare il monitoraggio di TaskManager.

    Ho scoperto che ogni istanza di un riferimento a un object Excel doveva essere esplicitamente rilasciata:

      xlApp = New Excel.Application xlWorkBooks = xlApp.Workbooks xlWorkBook = xlWorkBooks.Open(Me.txtFilePath.Text) xlWorkSheets = xlWorkBook.Worksheets xlWorkSheet = CType(xlWorkSheets(1), Excel.Worksheet) xlWorkBook.Close() xlWorkBooks.Close() xlApp.Quit() releaseObject(xlWorkSheet) xlWorkSheet = Nothing releaseObject(xlWorkSheets) xlWorkSheets = Nothing releaseObject(xlWorkBook) xlWorkBook = Nothing releaseObject(xlWorkBooks) xlWorkBooks = Nothing releaseObject(xlApp) xlApp = Nothing Private Sub releaseObject(ByVal obj As Object) Try System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj) obj = Nothing Catch ex As Exception obj = Nothing Finally GC.Collect() End Try End Sub 

    Si prega di usare questo

     Private Sub releaseObject(ByVal obj As Object) Try System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) obj = Nothing Catch ex As Exception obj = Nothing Finally GC.Collect() Try 'Dim MSExcelControl() As Process Dim iID As Integer Dim lastOpen As DateTime Dim obj1(10) As Process obj1 = Process.GetProcessesByName("EXCEL") lastOpen = obj1(0).StartTime For Each p As Process In obj1 If lastOpen < p.StartTime Then iID = p.Id Exit For End If Next For Each p As Process In obj1 If p.Id = iID Then p.Kill() Exit For End If Next Catch ex As Exception End Try End Try End Sub