在下面定義的類中,我使用公共屬性來保存Excel.Application
對象實例(這是我在單例類中的嘗試)。在完成之前在COM對象上運行例程?
每當Finalize
例程運行,並調用RestoreApp()
,它的一個InvalidComObjectException
(下面粘貼)上訪問該Application
對象的構件的第一次嘗試拋出。
我寫了這個簡單的測試程序來揣摩什麼鑼上,我覈實,我可以訪問此屬性之前被稱爲Finalize
的方法,但我總是得到InvalidComObjectException
當RetoreApp()
方法試圖訪問相同的財產。
的MSDN reference for Object Lifetime說:
之前釋放對象時,CLR自動調用該定義子最終確定程序對象最終確定 方法。最終化 方法可以包含需要執行的對象被銷燬 之前代碼...
然而,也許COM對象,其中該對象被部分破壞的特殊情況(RCW斷開形式基礎COM對象)在Finalize方法運行之前?我不知道 - 這似乎正在發生。
任何人都可以指示我如何確保ResoreApp()
過程在我的對象與COM對象斷開連接之前運行?
測試:
Sub Main()
Dim ExcelTest As New MyExcel
Debug.Print(ExcelTest.Excel Is Nothing)
Debug.Print(ExcelTest.Excel.DisplayStatusBar)
End Sub
的例外:已從其基礎RCW分離不能用來
{「COM對象。 「} _className :沒有
_COMPlusExceptionCode:-532462766
_data:沒有
_dynamicMethods:沒有
_exceptionMethod:沒有
_exceptionMethodString:沒有
_helpURL:沒有
_HResult:-2146233049
_innerException:沒有
_ipForWatsonBuckets:0
_message:「不能使用與其基礎RCW分離的COM對象。」
_remoteStackIndex:0
_remoteStackTraceString:Nothing
_safeSerializationManager:{System.Runtime.Serialization。SafeSerializationManager}
_source:沒有
_stackTrace:{爲SByte()}
_stackTraceString:沒有
_watsonBuckets:沒有
_xcode:-532462766
_xptrs:0
數據:{System.Collections.ListDictionaryInternal}
HelpLink:Nothing
HResult:-2146233049
InnerException:Nothing
IPForWatsonBuckets:0
IsTransient:False
消息:「已與其基礎RCW分離的COM對象無法使用」。
RemoteStackTrace:沒有
s_EDILock:{對象}
來源: 「mscorlib程序」
堆棧跟蹤:「在System.StubHelpers.StubHelpers.StubRegisterRCW(對象pThis)在
Microsoft.Office.Interop.Excel.ApplicationClass.get_DisplayStatusBar ()」
TargetSite:{無效StubRegisterRCW(System.Object的)}
WatsonBuckets:沒有
的類別:
Imports Microsoft.Office
Imports Microsoft.Office.Interop.Excel
Imports System.Windows.Forms
Public Class MyExcel
Dim CreateNew As Boolean
Dim Prepped As Boolean
Dim Prepping As Boolean
Dim pExcel As Microsoft.Office.Interop.Excel.Application
Dim pStatBar As Boolean
Dim pScreenUpdates As Boolean
Dim pEventsEnabled As Boolean
Dim pAlerts As Boolean
Private Property ScreenUpdates As Boolean
Get
Return pScreenUpdates
End Get
Set(value As Boolean)
pScreenUpdates = value
End Set
End Property
Private Property EventsEnabled As Boolean
Get
Return pEventsEnabled
End Get
Set(value As Boolean)
pEventsEnabled = value
End Set
End Property
Private Property StatBar As Boolean
Get
Return pStatBar
End Get
Set(value As Boolean)
pStatBar = value
End Set
End Property
Private Property AlertsDisplay As Boolean
Get
Return pAlerts
End Get
Set(value As Boolean)
pAlerts = value
End Set
End Property
Public ReadOnly Property Excel() As Microsoft.Office.Interop.Excel.Application
Get
Try
If Not CreateNew Then
If pExcel Is Nothing Then pExcel = GetObject([Class]:="Excel.Application")
End If
If pExcel Is Nothing Then pExcel = CreateObject("Excel.Application")
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
Return pExcel
End Get
End Property
Public Sub New(Optional ByVal NewExcel As Boolean = True)
CreateNew = NewExcel
PrepApp()
End Sub
Private Sub PrepApp()
'Set prepping to true to avoid creating a stack overflow
Try
With Me.Excel
ScreenUpdates = .ScreenUpdating
EventsEnabled = .EnableEvents
StatBar = .DisplayStatusBar
AlertsDisplay = .DisplayAlerts
.DisplayStatusBar = True
.ScreenUpdating = False
.EnableEvents = False
.DisplayAlerts = False
End With
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Private Sub RestoreApp()
'Restores the original values for screen updating, event triggers, and status bar display
Try
With Me.Excel
.DisplayStatusBar = StatBar
.ScreenUpdating = ScreenUpdates
.EnableEvents = EventsEnabled
.DisplayAlerts = AlertsDisplay
End With
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End Sub
Protected Overrides Sub Finalize()
RestoreApp()
MyBase.Finalize()
End Sub
End Class
我會將其標記爲答案,因爲它在技術上是正確的 - 但我現在要開始另一個問題,即如何使用COM對象安全地執行此操作。看到我的問題[這裏](http://stackoverflow.com/questions/31483635/when-to-call-marshal-finalreleasecomobject-and-more)關於如何處置COM對象,以及由@HansPassant鏈接的答案。 – CBRF23