Is it possible to intercept (or be aware of) COM Reference counting on CLR objects exposed to COM

前端 未结 10 1068
礼貌的吻别
礼貌的吻别 2020-12-08 02:56

I have rephrased this question.

When .net objects are exposed to COM Clients through COM iterop, a CCW (COM Callable Wrapper) is created, this sits between

10条回答
  •  粉色の甜心
    2020-12-08 03:49

    OK Folks, here's another attempt at it. You can actually use "Windows Script Components" to wrap your .NET COM objects and get finalization that way. Here's a full sample using a simple .NET Calculator which can Add values. I'm sure you'll get the concept from there, this totally avoids the VB-Runtime, ATL issues and uses the Windows Scripting Host which is available on every major WIN32/WIN64 platform.

    I created a simple COM .NET Class called Calculator in a namespaces called DemoLib. Note this implements IDisposable where for demo purpose I put something up on the screen to show it has terminated. I'm sticking totally to vb here in .NET and script to keep things simple, but the .NET portion can be in C# etc. When you save this file you'll need to register it with regsvr32, it will need to be saved as something like CalculatorLib.wsc.

     _
    Public Class Calculator
        Implements IDisposable
    #Region "COM GUIDs"
        ' These  GUIDs provide the COM identity for this class 
        ' and its COM interfaces. If you change them, existing 
        ' clients will no longer be able to access the class.
        Public Const ClassId As String = "68b420b3-3aa2-404a-a2d5-fa7497ad0ebc"
        Public Const InterfaceId As String = "0da9ab1a-176f-49c4-9334-286a3ad54353"
        Public Const EventsId As String = "ce93112f-d45e-41ba-86a0-c7d5a915a2c9"
    #End Region
        ' A creatable COM class must have a Public Sub New() 
        ' with no parameters, otherwise, the class will not be 
        ' registered in the COM registry and cannot be created 
        ' via CreateObject.
        Public Sub New()
            MyBase.New()
        End Sub
        Public Function Add(ByVal x As Double, ByVal y As Double) As Double
            Return x + y
        End Function
        Private disposedValue As Boolean = False        ' To detect redundant calls
        ' IDisposable
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    MsgBox("Disposed called on .NET COM Calculator.")
                End If
            End If
            Me.disposedValue = True
        End Sub
    #Region " IDisposable Support "
        ' 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
    #End Region
    End Class
    

    Next I create A Windows Script Component called Calculator.Lib which has a single method which returns back a VB-Script COM class which exposes the .NET Math Library. Here I pop up something on the screen during Construction and Destruction, note in the Destruction we call the Dispose method in the .NET library to free up resources there. Note the use of the Lib() function to return the .NET Com Calculator to the caller.

    
    
    
    
    
    
      
      
    
    
    
    

    Finally to tie it all together here's s sample VB script where you get dialogues showing creation, the calculation, dispose being called in the .NET library and finally Terminate in the COM component exposing the .NET Component.

    dim comWrapper
    dim vbsCalculator
    set comWrapper = CreateObject("Calculator.Lib")
    set vbsCalculator = comWrapper.GetMathLibrary()
    msgbox "10 + 10 = " & vbsCalculator.lib.Add(10, 10)
    msgbox "20 + 20 = " & vbsCalculator.lib.Add(20, 20)
    set vbsCalculator = nothing
    MsgBox("Dispose & Terminate should have been called before here.")
    

提交回复
热议问题