【问题标题】:InvalidCOMObjectException: COM object that has been separated from its underlying RCW cannot be used?InvalidCOMObjectException:无法使用已与其底层 RCW 分离的 COM 对象?
【发布时间】:2011-07-03 19:17:19
【问题描述】:

我在运行测试时抛出了这个异常:

测试方法OuvertureClasseur抛出异常:System.Runtime.InteropServices.InvalidComObjectException:已经与其底层RCW分离的COM对象无法使用...

虽然我的每个测试在单独运行时都通过了。

这是我的测试代码:

<TestClass()> _
Public Class FabriqueExcelTests
    Private Shared _xl As ApplicationClass

    <ClassInitialize()> _
    Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)
        _xl = New ApplicationClass()
        _xl.Visible = False
        _xl.ScreenUpdating = False
        _xl.DisplayAlerts = False
    End Sub

    <ClassCleanup()> _
    Public Shared Sub MyClassCleanup()
        _xl.Quit()
        _xl = Nothing
    End Sub

    <TestMethod()> _
    Public Sub ConstructeurParDefaut()
        Dim gestionnaire As GestionnaireExcel = New GestionnaireExcel()
        Assert.IsNotNull(gestionnaire)
        Assert.IsInstanceOfType(gestionnaire, GetType(GestionnaireExcel))
    End Sub

    <TestMethod()> 
    Public Sub CreationDUnFichierExcel()
        Dim fichier As String = "C:\Temp\CreationFichierExcel.xls"

        Using xl As GestionnaireExcel = New GestionnaireExcel()
            Dim classeur As Workbook = xl.CreerClasseur(fichier)
            classeur.Close()
            classeur = Nothing
        End Using

        Assert.IsTrue(File.Exists(fichier))
        File.Delete(fichier)
    End Sub

    <TestMethod()> _
    Public Sub OuvertureClasseur()
        Dim fichier As String = "C:\Temp\OuvertureClasseur.xls"

        _xl.Workbooks.Add(XlWBATemplate.xlWBATWorksheet)
        _xl.ActiveWorkbook.SaveAs(fichier)
        _xl.ActiveWorkbook.Saved = True
        _xl.Workbooks.Close()

        Using xl As GestionnaireExcel = New GestionnaireExcel()
            Dim classeur As Workbook = xl.OuvrirClasseur(fichier)
            Assert.AreEqual(fichier, classeur.FullName)
            classeur.Close()
            classeur = Nothing
        End Using

        File.Delete(fichier)
    End Sub

End Class

还有我的GestionnaireExcel 班级:

Public Class GestionnaireExcel
    Implements IDisposable

    Private _cultureOriginale As CultureInfo
    Private _disposedValue As Boolean = False        '' To detect redundant calls
    Private _excel As ApplicationClass

    Public Sub New()
        InitialiserExcel()
    End Sub

    '' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me._disposedValue Then
            If disposing Then
                '' TODO: free other state (managed objects).
                If (_excel IsNot Nothing) Then
                    _excel.Quit()
                    _excel = Nothing
                    System.Threading.Thread.CurrentThread.CurrentCulture = _cultureOriginale
                End If
            End If

            '' TODO: free your own state (unmanaged objects).
            '' TODO: set large fields to null.
        End If

        Me._disposedValue = True
    End Sub

    '' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        '' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    Public Function CreerClasseur(ByVal classeur As String) As Workbook
        _excel.Workbooks.Add(XlWBATemplate.xlWBATWorksheet)
        _excel.ActiveWorkbook.SaveAs(classeur)
        Return _excel.ActiveWorkbook
    End Function

    Private Sub InitialiserExcel()
        _cultureOriginale = System.Threading.Thread.CurrentThread.CurrentCulture
        System.Threading.Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")

        _excel = New ApplicationClass()
        _excel.DisplayAlerts = False
        _excel.ScreenUpdating = False
        _excel.Visible = False
    End Sub

    Public Function OuvrirClasseur(ByVal fichier As String) As Workbook
        Dim classeur As Workbook = _excel.Workbooks.Open(fichier _
                                                          , False, False _
                                                          , Type.Missing, Type.Missing,              Type.Missing, Type.Missing, Type.Missing, Type.Missing _
                                                          , False _
                                                          , Type.Missing, Type.Missing _
                                                          , False _
                                                          , Type.Missing, Type.Missing)
        Return classeur
    End Function
End Class

找到的相关问题

虽然我已经阅读并理解了这些问题和答案,但我似乎没有找到导致我的 OuvertureClasseur() 测试在我一起运行所有测试时失败的原因,而当我单独运行它时它工作得很好。

  1. COM object that has been separated from its underlying RCW cannot be used.
  2. WMI Exception: “COM object that has been separated from its underlying RCW cannot be used”
  3. COM object that has been separated from its underlying RCW cannot be used.
  4. COM object that has been separated from its underlying RCW can not be used - why does it happen?
  5. WPF Thread: “COM object that has been separated from its underlying RCW cannot be used.”

我已经跑了几个小时了,如果有任何帮助,我们将不胜感激。

提前致谢! =)

【问题讨论】:

  • 什么测试方法被命名为“method_name”?您正在使用 两个 Excel 实例,不好。丢弃也不完全健康。
  • 我编辑了我的帖子以反映什么是“method_name”。就是这个测试方法OuvertureClasseur

标签: visual-studio unit-testing com interop


【解决方案1】:

Excel 作为另一个进程执行。 classeur.Close() 中发生的事情可能是异步的,并且其中一些发生在处置 GestionnaireExcel 实例之后。

尝试注释掉 using 块,看看会发生什么。或者,如果 Excel COM 对象公开了一个属性,说明应用程序是否仍然存在,请尝试放入一个循环来监视它,并且在您确定它已经消失之前不要离开您的 using 块。

这只是一个猜测,但我看到没有其他人回答,所以我会把它扔在那里。

【讨论】:

  • 谢谢!由于我使用了底层 Excel 应用程序的两个实例,我猜想发生了一些异步调用。按照汉斯的评论说使用两个 Excel 实例不好,我相应地构建了我的程序,这解决了我的问题。谢谢!为您的时间和答案。 =)
猜你喜欢
  • 2011-07-15
  • 2011-11-21
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
  • 2012-09-17
相关资源
最近更新 更多