这是一个使用事件的非常简单的 .net <-> COM 互操作示例。
只要我在 .net 库的 Visual Studio 构建选项中使用 regasm 或register for com interop选项,此示例就可以正常工作。但我需要使用启用免注册互操作的并排清单进行部署。
该应用程序在并排模式下运行得很好,只是事件似乎消失了。我怀疑这是一些线程编组问题,但我似乎找不到正确的解决方案。
这当然是试图复制我在更复杂的互操作集成中遇到的问题。与实际问题相比,我在这里遇到的问题有一个区别:
两种解决方案都无法正确接收 .net 代码中引发的事件,而在无注册部署上运行时,当 .net dll 在注册表中注册时,这两种解决方案都按预期工作。但是:在“真实”项目中,当 System.Reflection.Target 失败时出现运行时错误。在这个简化的例子中,它只是默默地失败了。
我完全坚持这一点,因此非常欢迎任何和所有建议和解决方案。
如果有人在回答之前需要使用它,我已经将完整的代码放在 github 上:https ://github.com/Vidarls/InteropEventTest
.net 部分
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace InteropEventTest
{
    [Guid("E1BC643E-0CCF-4A91-8499-71BC48CAC01D")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComVisible(true)]
    public interface ITheEvents
    {
        void OnHappened(string theMessage);
    }
    [Guid("77F1EEBA-A952-4995-9384-7228F6182C32")]
    [ComVisible(true)]
    public interface IInteropConnection
    {
        void DoEvent(string theMessage);
    }
    [Guid("2EE25BBD-1849-4CA8-8369-D65BF47886A5")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(ITheEvents))]
    [ComVisible(true)]
    public class InteropConnection : IInteropConnection
    {
        [ComVisible(false)]
        public delegate void Happened(string theMessage);
        public event Happened OnHappened;
        public void DoEvent(string theMessage)
        {
            if (OnHappened != null)
            {
                Task.Factory.StartNew(() => OnHappened(theMessage));
            }
        }
    }
}
COM (VB6) 部分
Private WithEvents tester As InteropEventTest.InteropConnection
Private Sub Command1_Click()
    Call tester.DoEvent(Text1.Text)
End Sub
Private Sub Form_Load()
    Set tester = New InteropConnection
End Sub
Private Sub tester_OnHappened(ByVal theMessage As String)
    Text2.Text = theMessage
End Sub
我目前有以下用于部署的文件/文件夹结构:
Root
|-> [D] Interop.Event.Tester
    |-> Interop.Event.Tester.manifest
|-> [D] InteropEventTest
    |-> InteropEventTest.dll
|-> InteropEventTest.manifest
|-> InteropEventTest.tlb
|-> tester.exe
|-> tester.exe.manifest
清单文件内容:
Interop.Event.Test.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="Interop.Event.Tester" version="1.0.0.0" type="win32" processorArchitecture="x86"/>
</assembly>
InteropEventTest.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="InteropEventTest" version="1.0.0.0" type="win32"/>
<clrClass
   name="InteropEventTest.InteropConnection"
   clsid="{2EE25BBD-1849-4CA8-8369-D65BF47886A5}"
   progid="InteropEventTest.InteropConnection"
   runtimeVersion="v4.0.30319"
   threadingModel="Both"/>
<file name="InteropEventTest.tlb">
 <typelib
     tlbid="{5CD6C635-503F-4103-93B0-3EBEFB91E500}"
     version="1.0"
     helpdir=""
     flags="hasdiskimage"/>
</file>
<comInterfaceExternalProxyStub 
    name="ITheEvents" 
    iid="{E1BC643E-0CCF-4A91-8499-71BC48CAC01D}"
    proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
    baseInterface="{00000000-0000-0000-C000-000000000046}"
    tlbid="{5CD6C635-503F-4103-93B0-3EBEFB91E500}" />
</assembly>
tester.exe.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="tester.exe" version="1.0.0.0" type="win32" processorArchitecture="x86"/>
<dependency>
 <dependentAssembly>
  <assemblyIdentity name="InteropEventTest" version="1.0.0.0" type="win32"/>
 </dependentAssembly>
</dependency>
<dependency>
 <dependentAssembly>
  <assemblyIdentity name="Interop.Event.Tester" version="1.0.0.0" type="win32" processorArchitecture="x86"/>
 </dependentAssembly>
</dependency>
</assembly>