如何关闭Excel com对象并保存工作?
这让我快发疯了。我在这里找到了关于Excel com对象的类似帖子,但我尝试的解决方案中没有一个能够在代码运行完成后成功关闭Excel。Excel.dll将保留在TaskManager上 有人可以看看我下面的代码,让我知道为什么Excel无法关闭吗如何关闭Excel com对象并保存工作?,excel,Excel,这让我快发疯了。我在这里找到了关于Excel com对象的类似帖子,但我尝试的解决方案中没有一个能够在代码运行完成后成功关闭Excel。Excel.dll将保留在TaskManager上 有人可以看看我下面的代码,让我知道为什么Excel无法关闭吗 Try 'First get an application instance xlApp = New Excel.Application() 'Second open the workbook you
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不会总是完全关闭,甚至使用Quit方法也不会完全关闭 我想您可以迭代运行任务,强制终止它,但我不建议这样做。以下是我所做的: 将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;
}
}
此方法看起来像:
/// <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();
}
还有一个小助手函数:
public static void Release(Object releasable)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(releasable);
releasable = null;
}
这是我的最后一个街区;AFAIK这并没有在我们的应用程序中发布Excel失败。我们让Excel保持打开状态,并依靠用户关闭它。需要针对您引用的Excel对象自定义对Marshal.finalEleaseComObject的调用
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语句中删除参数:xlApp.Quit
在该行之后立即添加以下内容:Set xlApp=NothingMe now registered。另一件事-不要对Excel参数使用parens,除非将值传递到变量中。代码应如下所示:
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
这是一个大问题。如果用户在Excel中打开了另一个电子表格,该怎么办?你也会终止的!这个想法是完全终止作为COM对象创建的Excel实例。这个答案满足了提出的问题。+1是的,Cory是对的,这个问题显示了创建Excel新实例的自动化,并且正确地将可见性设置为“false”。在这种情况下,用户无法打开另一个电子表格,也不应允许用户打开。Cory,我不确定,在这里使用“FindWindow”API会有任何好处,我想你可以放弃它。当然不能指望标题是唯一的,下一个使用“GetWindowThreadProcessId”的部分应该总是有效的。只是一个想法。。。
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);
}
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