如何closuresExcel COM对象并保存工作?

这正在推动着我。 我发现这里有关Excel COM对象的类似post,但是我试过的解决scheme没有一个可以在我的代码完成运行后成功closuresExcel。 Excel.dll将留在TaskManager上。

有人可以看看我的代码下面,让我知道为什么Excel不会closures?

Try 'First get an application instance xlApp = New Excel.Application() 'Second open the workbook you need xlBook = xlApp.Workbooks.Open(_FileInfo.FullName) xlSheet = xlBook.Worksheets(sheetName) 'set visibility xlApp.Visible = False Dim row As Integer = 2 For Each t In upsRecordList While (row < upsRecordList.Count + 2) xlSheet.Cells(row, 1) = t.StartDate xlSheet.Cells(row, 2) = t.AccountTypeCode row += 1 End While Next Catch ex As Exception Throw ex Finally If Not xlApp Is Nothing Then GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() GC.WaitForPendingFinalizers() NAR(xlSheet) If Not xlBook Is Nothing Then xlBook.Close(SaveChanges:=True) NAR(xlBook) End If xlApp.Quit() NAR(xlApp) End If End Try Private Sub NAR(ByVal o As Object) Try Marshal.FinalReleaseComObject(o) Catch Finally o = Nothing End Try End Sub 

以下是我所做的:

保持你的Excel实例是一个单身人士:

 // Our singleton excel instance private static Excel.Application instance; /// <summary> /// Returns an instance of an Excel Application. /// This instance is a singleton. /// </summary> public static Excel.Application GetInstance { get { if (instance == null) { try { instance = new Excel.Application(); // Give the app a GUID so we can kill it later instance.Caption = System.Guid.NewGuid().ToString().ToUpper(CultureInfo.CurrentCulture); instance.Visible = false; } catch (COMException ce) { ShowMessage(ce.Message, MessageBoxIcon.Error); } } return instance; } } 

当你完成后,你可以摧毁它:

  public static void DestroyInstance() { if (instance != null) { // Close the workbooks object missing = Type.Missing; foreach (Excel.Workbook book in GetInstance.Workbooks) { book.Close(false, book.FullName, missing); } String appVersion = instance.Version; String appCaption = instance.Caption; IntPtr appHandle = IntPtr.Zero; if (Convert.ToDouble(appVersion, CultureInfo.CurrentCulture) >= 10) { appHandle = new IntPtr(instance.Parent.Hwnd); } // Quit and release the object instance.Workbooks.Close(); instance.Quit(); Release(instance); // Force a cleanup. MSDN documentation shows them making // two sets of collect and wait calls. System.GC.Collect(); System.GC.WaitForPendingFinalizers(); System.GC.Collect(); System.GC.WaitForPendingFinalizers(); EnsureProcessKilled(appHandle, appCaption); } } 

EnsureProcessKilled方法如下所示:

 /// <summary> /// This method contains a number of ways to try and kill /// the Excel process created when an instance is instantiated. /// </summary> /// <param name="windowHandle">Handle of the application window</param> /// <param name="caption">A custom GUI stored as the app's caption</param> public static void EnsureProcessKilled(IntPtr windowHandle, String caption) { NativeMethods.SetLastError(0); if (IntPtr.Equals(windowHandle, IntPtr.Zero)) { windowHandle = NativeMethods.FindWindow(null, caption); } if (IntPtr.Equals(windowHandle, IntPtr.Zero)) { // Can't find the window; assumed it's closed return; } int resourceId; int processId = 0; resourceId = NativeMethods.GetWindowThreadProcessId(windowHandle, ref processId); if (processId == 0) { // Can't get process id if (NativeMethods.EndTask(windowHandle) != 0) { return; // Success } } // Couldn't end it nicely, let's kill it System.Diagnostics.Process process; process = System.Diagnostics.Process.GetProcessById(processId); process.CloseMainWindow(); process.Refresh(); if (process.HasExited) { return; } // If we get here, it's being really stubborn. Say goodbye, EXCEL.EXE! process.Kill(); } 

你将需要NativeMethods类:

 public static class NativeMethods { [DllImport("user32.dll")] internal static extern int EndTask(IntPtr windowHandle); [DllImport("user32.dll", CharSet = CharSet.Unicode)] internal static extern IntPtr FindWindow(String className, String windowName); [DllImport("user32.dll")] internal static extern int GetWindowThreadProcessId(IntPtr windowHandle, ref int processId); [DllImport("kernel32.dll")] internal static extern IntPtr SetLastError(int errorCode); } 

还有一个小帮手function:

 public static void Release(Object releasable) { System.Runtime.InteropServices.Marshal.ReleaseComObject(releasable); releasable = null; } 

你的代码很好。 当您释放对象时,甚至通过使用Quit方法,Excel不会总是完全closures。

我想你可以遍历正在运行的任务,强制终止它,但我不build议这样做。

这是我的最后一块 AFAIK这并没有在我们的应用程序中发布Excel。 我们打开Excel并依靠用户closures它。 对Marshal.FinalReleaseComObject的调用将需要为您引用的Excel对象自定义。

  finally { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); // Calls are needed to avoid memory leak Marshal.FinalReleaseComObject(sheet); Marshal.FinalReleaseComObject(book); Marshal.FinalReleaseComObject(excel); } 

从Quit语句中删除parens:xlApp.Quit

在该行之后立即添加:Set xlApp = Nothing

我再次(现在注册)。 另一件事 – 不要使用Excel的参数parens,除非你传递一个值到一个variables。 代码应该是这样的:

  If Not xlApp Is Nothing Then GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() GC.WaitForPendingFinalizers() NAR(xlSheet) If Not xlBook Is Nothing Then xlBook.Close True xlBook = Nothing End If xlApp.Quit xlApp = Nothing End If