【问题标题】:Cannot close Excel.exe after killing it from Task Manager从任务管理器中杀死 Excel.exe 后无法关闭它
【发布时间】:2016-03-18 03:07:28
【问题描述】:

我正在使用 C# 中的 Visual Studio 2015 Community,以及独立的 Office 2013。

以下代码用于打开和关闭 Excel。然后我添加了代码来打开特定的工作表,如下面的示例 2 所示。而且,这行得通,Excel 正确关闭。

然后我移动了一些东西,但忘记使用 ReleaseComObject 作为工作表并且 Excel 保持打开状态,所以我在任务管理器中手动将其关闭。

现在,以下示例均无效。在我不小心忘记释放 COM 对象后,Excel 永远不会关闭,除非我重新启动机器。

示例 1

private bool loadExcel()
{
    // Open Excel
    Excel.Application myApp = new Excel.Application();
    // Hide Excel
    myApp.Visible = false;
    GSIWorkbook = myApp.Workbooks.Open( "D:\\Test.xlsx" );
    // Cleanup
    GSIWorkbook.Close( false );
    // Manual disposal because of COM
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( GSIWorkbook ) != 0 )
    { }

    myApp.Application.Quit();
    myApp.Quit();
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( myApp ) != 0 )
    { }

    myApp = null;
    GSIWorkbook = null;

    GC.Collect();
    GC.WaitForPendingFinalizers();
    return true;

} // End loadExcel

示例 2

private bool loadExcel()
{
    // Open Excel
    Excel.Application myApp = new Excel.Application();
    // Hide Excel
    myApp.Visible = false;
    GSIWorkbook = myApp.Workbooks.Open( "D:\\Test.xlsx" );

    for ( int counter = 1; counter < 100; counter++ )
    {
        try
        {
            GSIWorksheet = GSIWorkbook.Sheets[counter];
            if ( GSIWorksheet.Name == _gsi2Sheet )
                break;
        }
        catch
        {
            continue;
        }
    }

    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( GSIWorksheet ) != 0 )
    { }

    // Cleanup
    GSIWorkbook.Close( false );
    // Manual disposal because of COM
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( GSIWorkbook ) != 0 )
    { }

    myApp.Application.Quit();
    myApp.Quit();
    while ( System.Runtime.InteropServices.Marshal.ReleaseComObject( myApp ) != 0 )
    { }

    myApp = null;
    GSIWorkbook = null;

    GC.Collect();
    GC.WaitForPendingFinalizers();
    return true;
} // End loadExcel

【问题讨论】:

  • 你是说VS社区吗?视觉工作室?
  • "Excel 永远不会关闭,除非我重新启动我的机器。" ...或者,只需打开任务管理器并终止所有剩余的“excel.exe”进程。
  • 正如我上面所说,我使用的是 C#,而不是 VB,而且我不会在任何地方使用“.Add”。在任务管理器中杀死不是一个干净的解决方案,使用 proc.Kill() 将杀死所有 Excel 实例。我知道我可以发现进程 ID (PID),然后只杀死该进程。但这也感觉像一个kluge。完成后必须有一种干净的方法来关闭 Excel。

标签: c# excel


【解决方案1】:

如果您向我们展示您对 excel 对象的完整用法,我敢打赌您会发现您违反了 2 点规则。我知道这听起来很荒谬,但我认为您无意中创建了 Excel 或 GC 无法处理的对象实例,然后它就无法正确关闭。 (称为 Runtime Callable Wrappers)

当你使用 - 比如说 - 这个代码时:

xlWorkBook = xlApp.Workbooks.Add

...您实际上是造成问题的原因。您需要创建一个指向Workbooks 的变量并直接使用它并处理它。 链接示例:

Dim xlApp As New Excel.Application
Dim xlWorkBooks As Excel.Workbooks = xlApp.Workbooks
Dim xlWorkBook As Excel.Workbook = xlWorkBooks.Add()

....所有你的代码,然后

xlApp.Quit()

If Not xlWorkBook Is Nothing Then
    Marshal.FinalReleaseComObject (xlWorkBook)
    xlWorkBook = Nothing
End If
If Not xlWorkBooks Is Nothing Then
    Marshal.FinalReleaseComObject (xlWorkBooks)
    xlWorkBooks = Nothing
End If
If Not xlApp Is Nothing Then
    Marshal.FinalReleaseComObject (xlApp)
    xlApp = Nothing
End If

xlApp.Quit()

详情请看这里:

http://www.siddharthrout.com/2012/08/06/vb-net-two-dot-rule-when-working-with-office-applications-2/

【讨论】:

  • 正如我上面所说,我使用的是 C#,而不是 VB,而且我不会在任何地方使用“.Add”。在任务管理器中杀死不是一个干净的解决方案,使用 proc.Kill() 将杀死所有 Excel 实例。我知道我可以发现进程 ID (PID),然后只杀死该进程。但这也感觉像一个kluge。完成后必须有一种干净的方法来关闭 Excel。
  • 我完全不在乎你想在应用程序中不使用 QUIT 的情况下如何杀死 Excel。我的回答也不是关于 .ADD 的。我的回答表明,在任何情况下,您都不能使用 Runtime Callable Wrapper 并期望优雅地关闭 Excel。两个点“规则”适用于 ANY 和 ALL 方法,而不仅仅是 .ADD
  • 我的答案也不是特定于语言的... C#、VB.NET、VB6 ...您选择的任何语言都会有同样的问题。请发布与提供的答案相关的 cmets,我注意到您发布了两次,我认为您的评论是针对我的答案...
  • 而您的代码明确违反了myApp.Workbooks.Open(行中的规则
  • 知道了。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多