是否有可能拦截(或知道)暴露于COM CLR对象COM引用计数有可能、对象、COM、CLR

由网友(败家小男人)分享简介:我已经改写了这个问题。的在.NET对象通过COM iterop暴露在COM客户端,CCW(的 COM可调用包装)创建,该坐的COM客户端和管理的.NET对象之间。When .net objects are exposed to COM Clients through COM iterop, a CCW (COM...

我已经改写了这个问题。的

在.NET对象通过COM iterop暴露在COM客户端,CCW(的 COM可调用包装)创建,该坐的COM客户端和管理的.NET对象之间。

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

在COM环境,对象保持其他对象得它引用的数目的计数。对象被删除/释放/收集时引用计数为零。这意味着,COM对象的终止是确定的(我们使用使用/ IDispose在.NET中的确定性终止,终结对象是不确定性的)。

In the COM world, objects keep a count of the number of references that other objects have to it. Objects are deleted/freed/collected when that reference count goes to Zero. This means that COM Object termination is deterministic (we use Using/IDispose in .net for deterministic termination, object finalizers are non deterministic).

每个CCW是一个COM对象,它是参考计数像任何其他COM对象。当向CCW模具(参考计数变为零)GC将无法找到CLR对象向CCW包裹,和CLR对象符合集合。快乐的日子,一切都很好,与世界同步。

Each CCW is a COM object, and it is reference counted like any other COM object. When the CCW dies (reference count goes to Zero) the GC won't be able to find the CLR object the CCW wrapped, and the CLR object is eligible for collection. Happy days, all is well with the world.

我想要做的就是抓时,CCW死亡(即当其引用计数为零),并以某种信号,这对CLR对象(例如,通过调用Dispose方法的管理对象)。

What I would like to do is catch when the CCW dies (i.e. when its reference count goes to zero), and somehow signal this to the CLR object (e.g. By calling a Dispose method on the managed object).

那么,是不是可以知道什么时候的 COM可调用包装一个CLR类变为零? 和/或 是否有可能提供本人实施的AddRef和放大器; ReleaseRef在.NET幼儿工作员?

So, is it possible to know when the reference count of a COM Callable Wrapper for a CLR class goes to Zero? and/or Is it possible to provide my implementation of AddRef & ReleaseRef for CCWs in .net?

如果没有替代方案是实现这些DLL的ATL(我不需要任何帮助,ATL,谢谢)。它不会是火箭科学,但我不愿意这样做,因为我是在公司内部唯一的开发与任何真实世界的C ++或任何ATL。

If not the alternative is to implement these DLLs in ATL (I don't need any help with ATL, thanks). It wouldn't be rocket science but I'm reluctant to do it as I'm the only developer in-house with any real world C++, or any ATL.

背景 我重新写一些旧VB6的ActiveX DLL文件中的.NET(C#是准确的,但是这更多的是.NET / COM互操作问题,而不是一个C#的问题)。一些老VB6的对象取决于引用计数来进行操作时,对象终止(见上文引用计数的解释)。这些DLL的不包含重要的商业逻辑,他们是公用事业和辅助功能,我们提供给我们使用VBScript集成的客户。

Background I'm re-writing some old VB6 ActiveX DLLs in .net (C# to be exact, but this is more a .net / COM interop problem rather than a C# problem). Some of the old VB6 objects depend on reference counting to carry out actions when the object terminates (see explaination of reference counting above). These DLL's don't contain important business logic, they are utilities and helper functions that we provide to clients that integrate with us using VBScript.

我不想做什么

引用计数.NET对象,而不是 在使用垃圾收集器。 我很高兴与GC,我 问题不在于与GC。 使用对象终结。终结是 非确定性的,在这种情况下我 需要确定的终端(如 在.NET中的使用/ IDispose成语) 在非托管的C实现IUnknown ++ 如果我去了C ++的路线,我将使用 ATL,谢谢。 在使用VB6解决这个问题,或再使用 VB6的对象。的全部要点 这个练习是消除我们的构建 在VB6的依赖。 Reference count .net objects instead of the using the Garbage Collector. I'm quite happy with the GC, my problem isn't with the GC. Use object finalizers. Finalizers are non deterministic, in this instance I need deterministic termination (like the Using/IDispose idiom in .net) Implement IUnknown in unmanaged C++ If I've to go the C++ route I'll use ATL, thanks. Solve this using Vb6, or re-using the VB6 objects. The entire point of this exercise is to remove our build dependence on Vb6.

感谢 BW

接受的答案 伙计一千感谢Steve施泰纳,谁想出的唯一的(可能是可行的),基于.NET的答案,Earwicker,谁想出了一个很简单的ATL的解决方案。

The Accepted Answer Folks a thousand thanks to Steve Steiner, who came up with the only (possibly workable) .net based answer, and Earwicker, who came up with a very simple ATL solution.

但接受的答案去Bigtoe,谁建议包裹在VBScript对象的.NET对象(我没有考虑要诚实),有效地提供了一个简单的VBScript的解决方案,以一个VBScript问题。

However the accepted answer goes to Bigtoe, who suggests wrapping the .net objects in VbScript objects (which I hadn't considered to be honest), effectively providing a simple VbScript solution to a VbScript problem.

感谢所有。

推荐答案

确定伙计们,这里是它的另一个尝试。实际上,你可以使用Windows脚本组件来包裹你的.NET COM对象,并得到最终确定的方式。下面是使用简单的.NET计算器可以添加值的全样本。我敢肯定你会从那里得到的概念,这完全避免了VB运行时,ATL问题并使用Windows脚本宿主是提供所有主要WIN32 / WIN64平台。

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.

我创建了一个简单的COM .NET类的命名空间称为DemoLib叫计算器。请注意,这实现IDisposable,其中用于演示目的,我把东西在屏幕上,以显示它已经终止。我坚持完全在这里的VB .NET和脚本,让事情变得简单,但是.NET部分可以在C#等等。当你保存这个文件,你需要用REGSVR32注册它,它需要被保存因为像CalculatorLib.wsc。

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.

<ComClass(Calculator.ClassId, Calculator.InterfaceId, Calculator.EventsId)> _
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

接下来创建一个Windows脚本组件称为Calculator.Lib它有它返回回到这暴露了.NET数学库中的VB脚本COM类的单一方法。在这里,我弹出屏幕上的内容建构与解构过程中,记下我们所说的在.net库中的Dispose方法以释放资源存在的破坏。注意,这里使用的库()函数的返回.NET的COM计算器给调用者。

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.

<?xml version="1.0"?>
<component>
<?component error="true" debug="true"?>
<registration
    description="Demo Math Library Script"
    progid="Calculator.Lib"
    version="1.00"
    classid="{0df54960-4639-496a-a5dd-a9abf1154772}"
>
</registration>
<public>
  <method name="GetMathLibrary">
  </method>
</public>
<script language="VBScript">
<![CDATA[
Option Explicit
'-----------------------------------------------------------------------------------------------------
' public Function to return back a logger.
'-----------------------------------------------------------------------------------------------------
function GetMathLibrary()
    Set GetMathLibrary = New MathLibrary
end function
Class MathLibrary
    private dotNetMatFunctionLib
  private sub class_initialize()
    MsgBox "Created."
    Set dotNetMatFunctionLib = CreateObject("DemoLib.Calculator")
  end sub
  private sub class_terminate()
        dotNetMatFunctionLib.Dispose()
        Set dotNetMatFunctionLib = nothing
    MsgBox "Terminated."
  end sub
  public function Lib()
    Set Lib = dotNetMatFunctionLib
  End function
end class
]]>
</script>
</component>

最后,以配合它一起在这里就是你得到的对话显示出的创作,计算,处理被称为在.net库中,最后终止于COM组件暴露的.NET组件s的采样VB脚本。

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.")
阅读全文

相关推荐

最新文章