InvalidCOMObjectException: COM object that has bee

2019-07-16 04:23发布

I'm getting this exception thrown when I run my tests:

Test method OuvertureClasseur threw exception: System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used...

though each of my test passes when ran individually.

Here's my tests code:

<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

And my GestionnaireExcel class:

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

Related questions found

Though I have read and understand these questions and answers, I don't seem to find what causes my OuvertureClasseur() test to fail when I run all my tests together, and it works just fine when I run it individually.

  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.”

I have been running around for few hours now, and any help will gladly be appreciated.

Thanks in advance! =)

1条回答
叼着烟拽天下
2楼-- · 2019-07-16 05:09

Excel's executing as another process. It's possible that what's happening in classeur.Close() is asynchronous, and that some of it is taking place after the GestionnaireExcel instance is disposed.

Try commenting out the using block and see what happens. Or if the Excel COM object exposes a property saying whether the app is still alive, try putting in a loop to monitor that and not leave your using block until you're sure it's gone.

This is just a guess, but I see nobody else has answered yet, so I'll toss it out there.

查看更多
登录 后发表回答