在VB.NET中调用Marshal.FinalRelease后,Excel的实例仍然存在

时间:2012-09-13 19:45:43

标签: vb.net excel excel-interop

我已经在这里查看了一些关于在程序运行后删除excel实例的提示,但是这些建议似乎都没有用。当我最初运行它时,它将创建一个excel实例,但是当程序仍在运行时,我通过单击按钮重新运行此代码;它将创建另一个excel实例,但这一次它删除了它创建的实例,只留下了程序最初初始运行时创建的实例。

到目前为止我的代码是什么:(自2012年9月14日起更新的代码)

Private Sub GetBatchFileContents()

    Dim xlApp As Excel.Application
    Dim xlWB As Excel.Workbook
    Dim xlWS As Excel.Worksheet
    Dim xlRan As Excel.Range
    Dim xlVal(,) As Object
    Dim lastRow As Int32

    xlApp = New Excel.Application()
    xlWB = xlApp.Workbooks.Open(TextBox1.Text.ToString(), _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing, _
                                Type.Missing)
    xlWS = xlWB.Worksheets.Item(1)
    lastRow = xlWS.Cells(xlWS.Rows.Count, 1).End(Excel.XlDirection.xlUp).Row
    xlRan = xlWS.Range(xlWS.Cells(1, 1), xlWS.Cells(lastRow, 130))
    xlVal = xlRan.Value2()
    ReleaseObj(xlRan)
    ReleaseObj(xlWS)
    xlWB.Close(False, Type.Missing, Type.Missing)
    ReleaseObj(xlWB)
    xlApp.Quit()
    ReleaseObj(xlApp)

End Sub

Private Sub ReleaseObj(ByRef obj As Object)

    Try
        Marshal.FinalReleaseComObject(obj)
    Catch ex As Exception
        Stop
    Finally
        obj = Nothing
    End Try

    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()

End Sub

提前感谢您的反馈!

2 个答案:

答案 0 :(得分:1)

我和你描述的问题非常相似。通过使用此示例代码,它对我有用

' set all Excel related  objects to nothing
columnHeaders = Nothing
range = Nothing
endCell = Nothing
startCell = Nothing
excelSheet = Nothing
excelSheets = Nothing
excelWorkbook.Close()
excelWorkbook = Nothing
excelApp.Quit()
' release com ressources 
 Marshal.FinalReleaseComObject(excelApp)  ' !

excelApp = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()

在MSDN上查看FinalReleaseComObjectReleaseComObject

修改

Private Sub GetBatchFileContents()
    Dim xlApp As Excel.Application
    Dim xlWB As Excel.Workbook
    Dim xlWS As Excel.Worksheet
    Dim xlRan As Excel.Range
    Dim xlVal(,) As Object
    Dim lastRow As Int32

    xlApp = New Excel.Application()
    xlWB = xlApp.Workbooks.Open(TextBox1.Text.ToString(), _
                                Type.Missing, Type.Missing,  Type.Missing,  Type.Missing,  Type.Missing, _
                                Type.Missing,  Type.Missing,  Type.Missing, Type.Missing, Type.Missing, _
                                Type.Missing,  Type.Missing, Type.Missing,  Type.Missing)
    xlWS = xlWB.Worksheets.Item(1)

    ' original
    'lastRow = xlWS.Cells(xlWS.Rows.Count, 1).End(Excel.XlDirection.xlUp).Row

    ' new
    Dim range1 As Excel.Range
    range1 = xlWS.Cells(xlWS.Rows.Count, 1)
    Dim range2 As Excel.Range
    range2 = range1.End(Excel.XlDirection.xlUp)
    lastRow = range2.Row
    ReleaseObj(range1)
    ReleaseObj(range2)

    ' original
    'xlRan = xlWS.Range(xlWS.Cells(1, 1), xlWS.Cells(lastRow, 130))

    ' new
    Dim range1_1 As Excel.Range
    range1_1 = xlWS.Cells(1, 1)
    Dim rangeLastRow_130 As Excel.Range
    rangeLastRow_130 = xlWS.Cells(lastRow, 130)
    xlRan = xlWS.Range(range1_1, rangeLastRow_130)
    ReleaseObj(range1_1)
    ReleaseObj(rangeLastRow_130)

    ' unchanged
    xlVal = xlRan.Value2()
    ReleaseObj(xlRan)
    ReleaseObj(xlWS)
    xlWB.Close(False, Type.Missing, Type.Missing)
    ReleaseObj(xlWB)
    xlApp.Quit()
    ReleaseObj(xlApp)
End Sub

我将您的代码更改为将每个可能的COM实例分配给变量明确释放它!但由于它在我的电脑上工作正常,我无法测试它。

此外,我发现article描述了可能导致您描述的行为的内容。

  

您的Excel加载托管AddIn(共享AddIn或VSTO AddIn),其中   打破规则。应用程序自动化Excel后   应用程序,Excel应用程序无法正确退出,因为   加载的AddIn有一些未发布的底层RCW。在这种情况下,   即使您的自动化客户端终止,Excel也不会退出。所以   解决此类问题的一个步骤是禁用所有问题   AddIns以隔离根本原因。(参见文章了解详细信息)

如果我的其中一个提议适合你,请告诉我!

答案 1 :(得分:0)

我所做的基本概要。我在工作簿功能的大图中将此逻辑合并到锁定过程中。我不得不关闭Echo,否则最终用户得到了两个实例之间的华而不实的交互,因为我激活了一个工作簿/工作表,然后移动到另一个工作簿/工作表。你必须在这里使用一些东西;)。

这是我在项目srcwb.Close SaveChanges:=False中使用的所有内容,它关闭了文件。我过去所做的是获取Application的对象引用,这样我就可以获得实例的系统ID并从应用程序中关闭它。当然,假设您拥有Code-Behind的VBA / Project控件,而不仅仅是平面数据文件。

否则,您必须在Parent文件中创建一个Collection Object,并在Collection中打开一个新的实例存储应用程序实例,然后定期运行Collection并验证Instance是否处于活动状态。< / p>