Excel-Prozess nicht schließen VB.net
Erstelle ich eine excel-Datei mit interop.excel und der Prozess schließt sich nicht.
Dies ist der code, den ich versuche zu verwenden.
Private Sub converToExcel(fileLoc As String, ds As DataSet)
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkBooks As Excel.Workbooks
Dim xlWorkSheet As Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
Dim i As Integer
Dim j As Integer
xlApp = New Excel.Application
xlWorkBooks = xlApp.Workbooks
xlWorkBook = xlWorkBooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
For i = 0 To ds.Tables(0).Rows.Count - 1
For j = 0 To ds.Tables(0).Columns.Count - 1
xlWorkSheet.Columns.NumberFormat = "@"
xlWorkSheet.Cells(i + 1, j + 1) = String.Format("{0}", ds.Tables(0).Rows(i).Item(j).ToString())
Next
Next
xlWorkSheet.SaveAs(fileLoc)
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlWorkSheet)
releaseObject(xlWorkBook)
releaseObject(xlWorkBooks)
releaseObject(xlApp)
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
Ich glaube, ich bin fehlt ein COM-Objekt, kann aber nicht scheinen, um eine Lösung zu finden.
Auch als Hinweis, dieser unter der 64-bit-Windows-8.
Jede Hilfe würde groß sein!
Dank
- Und Sie sind sicher, dass dies nicht eine Instanz, die Links von vorherigen Tests?
- ja, ich check den Task-Manager nach jedem test und entfernen Sie alle Instanzen von excel.
- Ich glaube nicht, dass dies die Ursache für dein problem, aber
releaseObject
können nicht alles tun, Sie denken, es tut. Da bist du vorbeiobj
ByVal
, dieobj = Nothing
nicht haben keine Auswirkung auf diexlWorkSheet
,xlWorkBook
etc. Variablen. - Geändert releaseObject zu byref statt byval gleiche Ergebnis.
- Wirkt sich das hinzufügen xlWorkbooks.Schließen entfernen Sie den Prozess? Wenn nicht, würde ich empfehlen, den code schrittweise Durchlaufen, zu sehen, wenn Prozesse geschaffen werden, und dann bestimmen, was entfernt in Richtung auf das Ende deiner Sub.
- ...und ist die Letzte Excel-Datei generiert wird? Gibt es eine Möglichkeit, dass dein Sub ist erroring und trat um sich, bevor er sich löst Referenzen? Ich steckte Sie Ihren code in einen editor, und das Tat es, wenn ich lieferte ein dataset mit keine Tabellen. Wenn ich die Versorgung ein Datensatz mit mindestens einer Tabelle, dann ist dein code lief fein und veröffentlicht alle Referenzen.
- Der sub ist nicht erroring vor dem release, wenn ich einen Schritt durch Sie alles ordnungsgemäß ausgeführt wird. Auch die sub-Aufruf in der Fehlerbehandlung, so würde es kick-out zu. Die einzige andere Sache, die ich denken kann, ist, dass es unter Windows 8 läuft.
- Ich weiß, das ist eine dumme Frage, aber Ihre Berufung Sub nicht festlegen Verweise auf Excel, richtig?
- Die einzige andere Zeit, die in der Anwendung ich mich auf excel zugegriffen wird, die über eine oleDB-Verbindung nicht interop. Ich Tat, werfen Sie den original-code in einer Konsole app in VS läuft auf windows 7 und es funktioniert einwandfrei. Auf windows 8 der Prozess bleibt offen.
- Sie schließen, sobald die Anwendung beendet wird?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Manuelle Speicherverwaltung wie das eben nie funktioniert. Dies ist ein problem, das bekannt ist für sehr lange Zeit, und der Kern Grund dafür, dass Müll-Sammler waren erfunden. Die Programmierer einfach für immer vergessen, um Speicher freizugeben.
Wird es extra hart, wenn Sie nicht sehen können den Arbeitsspeicher verwendet wird. Das ist sicherlich der Fall in Ihrem code, die
xlWorkSheet.Cells(i + 1, j + 1)
Ausdruck verwendet nicht weniger als drei Referenzen. Eine für das range-Objekt zurückgegeben, indem die Zellen-Eigenschaft, eine für ein sub-range "- Objekt ausgewählti+1
und eine für die sub-range " - Objekt ausgewähltj+1
. Sehr schöne syntax-Zucker-zur Verfügung gestellt von der VB.NET Sprache, schreiben von COM-code, ohne ist es ziemlich doggone schmerzhaft. Aber nicht hilfreich, lassen Sie die Referenzen. Nicht nur können Sie es nicht sehen in deinem source-code, es gibt absolut nichts, was der debugger für Sie tun können sehen Sie.Dies ist sehr viel ein problem in .NET, es hat einen garbage collector und kann es sehen alles. Das grundlegendste problem ist, dass Sie nicht ihm eine chance geben, Ihr problem zu lösen. Die Fehler, die Sie gemacht ist, dass Sie gestoppt. Wahrscheinlich durch setzen eines Breakpoints auf die Letzte Anweisung und dann suchen die im Task-Manager und sehen Excel.exe immer noch läuft. Ja, das ist normal. Garbage collection ist nicht sofortige.
Aufruf von GC.Collect() ist, soll es sofort, aber das funktioniert nicht in dem speziellen Fall der Ausführung des Debug-build des Projekts. Die Lebensdauer von lokalen Variablen wird dann erweitert, um das Ende der Methode, damit Sie sehen, Sie in die Autos/Einheimischen/Watch Fenster. In anderen Worten, GC.Collect() nicht wirklich sammeln alle des interface-Referenzen. Mehr über das Verhalten in dieser Beitrag.
Die einfache Lösung ist, um nicht aufhören. Halten Sie daran, nützliche Dinge zu geben, die der garbage collector einen Grund zu laufen. Oder lassen Sie Ihr Programm beenden, da es fertig ist, wird Excel beendet, wenn der finalizer-thread läuft zum letzten mal. Das funktioniert, weil die lokalen Variablen, die Referenzen sind nicht im Lieferumfang mehr.
Aber jeder will, dass die Korrektur sowieso. Sie bekommen es durch löschen aller releaseObject () - Aufrufe. Und tun Sie es wie folgt statt:
Oder in anderen Worten, die Kraft, eine Sammlung nach der Methode zurückgegeben hat. Die lokalen Variablen nicht mehr im Rahmen, so dass Sie nicht halten, um eine Excel-Referenz. Es wird jetzt auch funktionieren, wenn Sie Debuggen, wie es schon damals, als Sie lief die Version ohne debugger.
Versuchen System.- Laufzeit.InteropServices.Marschall.FinalReleaseComObject, das sollte helfen... auch sollten Sie rufen xlWorkBook.Close() und xlapp.beenden Sie, wenn ich mich Recht erinnere. Zuerst nennen Sie und setzen Sie Sie zu nichts.
Den GC.Sammeln macht nicht viel Sinn, wo Sie es platziert, wenn überhaupt sollten Sie es nennen wenn du wieder von
converToExcel
. Auch Sie müssen warten, bis Finalizer ausgeführt werden. Ich persönlich denke, dass Hans' Antwort ist der Weg zu gehen, aber ich weiß aus eigener Erfahrung schreiben, office-addins in C# und manchmal ist es notwendig, um manuelle Referenz zählen, insbesondere, wenn Sie benötigen, um die Kompatibilität mit älteren office-Versionen. (Es gibt viele dokumentierte Probleme, insbesondere bei der Behandlung von Ereignissen aus dem Amt, die können nur zuverlässig gelöst durch manuelles reference counting. Auch einige COM-Bibliotheken nicht mögen, wenn veröffentlicht, in der falschen Reihenfolge von GC, aber das ist nicht der Fall mit office.)Also auf, um das eigentliche problem in deinem code: es gibt drei intermediate COM-Objekte nicht freigegeben, hier:
xlWorkBook.Sheets
gibt eine collection zurück gebenExcel.Sheets
xlWorkSheet.Columns
gibt ein COM-Objekt vom TypExcel.Range
xlWorkSheet.Cells
gibt auch einenExcel.Range
ObjektNeben dieser, wenn Marschall.ReleaseComObject eine exception wirft Sie etwas falsch gemacht haben in Ihrem Handbuch "reference counting", daher würde ich Sie nicht wickeln Sie es in einem exception-handler. Wenn dabei manuelle Referenz zu zählen, die Sie loslassen müssen, jedes COM-Objekt, einmal für jedes mal, wenn Sie über den COM->NETTO-Grenze, d.h. die
Excel.Range
Objekte müssen freigegeben werden in jeder iteration der Schleife.Hier ist code, der ordnungsgemäß beendet Excel für mir:
Wenn Sie wollen besonders vorsichtig sein, wollen Sie die Ausnahmen behandeln, die aus der office-API und rufen ReleaseComObject innen endlich-Klauseln. Es kann hilfreich sein zu definieren, ein generischer wrapper und schreiben, mit Punkt statt des try-finally (machen die wrapper-Struktur, die nicht einer Klasse, so brauchen Sie nicht reservieren der Wrapper auf dem heap).
Endlich gelöst 🙂
verwenden Sie diese Methode,
Diese Methode schließt especific Prozess eröffnet.
Habe ich nicht gesehen, jemanden richtig ansprechen, was war vorkommenden und stattdessen versucht, ein Werk zu schaffen Lösungen für Sie.
Was hier passiert, ist, dass die Arbeitsmappe wird aufgefordert, in den hintergrund, um gerettet zu werden. In Ihrem code, Sie speichern Sie das Arbeitsblatt und die Arbeitsmappe. Sie können entweder trick und setzen Sie den gespeicherten Zustand der Arbeitsmappe auf wahr oder speichern Sie die Arbeitsmappe vor beenden der excel-Anwendung.
War ich auch mit diesem Problem. Die Excel-Prozesses ausgeführt würde, die gesamte Zeit der Anwendung offen war. Durch das hinzufügen der xlWorkBook.Gesichert = True Zeile würde der Vorgang enden, wenn der Aufruf xlApp.Beenden(). In meinem Fall, habe ich nicht brauchen, speichern Sie die excel-Datei, nur Referenz für die Werte.
Option #1 - speichern Sie die Arbeitsmappe nicht:
Option #2 - Speichern Sie die Arbeitsmappe in eine neue Datei:
Option #3 - Speichern Sie die Arbeitsmappe auf einer vorhandenen Datei:
.Quit () - Methode:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel._application.quit?view=excel-pia#Microsoft_Office_Interop_Excel__Application_Quit
.Saved () - Methode:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel._workbook.saved?view=excel-pia#Microsoft_Office_Interop_Excel__Workbook_Saved