问题描述
基本上,我有一个 C++ ATL DCOM 服务,我试图用 C# COM+ 服务替换它,但在尝试注册我的事件时遇到了问题。我能够通过以下示例重现该问题
MyInterface.idl:
import "oaidl.idl";
import "ocidl.idl";
[
object,uuid(993D13F8-5752-4046-9179-3BABD1513A8F),pointer_default(unique)
]
interface MyInterface : Idispatch
{
HRESULT MyFunc1([in] BSTR lid);
};
[
uuid(841E7E02-2ED3-412B-928B-F9C01CE300CE),version(1.0)
]
library MyInterfaceLibrary
{
importlib("stdole2.tlb");
[
uuid(6BFA2661-5286-4C7A-973B-5BD14A654B6D)
]
dispinterface MyInterfaceEvents
{
properties:
methods:
[id(1)] HRESULT MyEvent1([in] BSTR message);
};
[
uuid(0E10489A-4BD0-47FF-9739-843DF8072B0E)
]
coclass MyInterfaceImpl
{
[default] interface MyInterface;
[default,source] dispinterface MyInterfaceEvents;
};
};
我使用这个 IDL 来生成我的 C++ 和 .Net 互操作库。互操作库经过 GAC 处理,并且据我所知,本机 DLL 已注册正常。
MyComServerCPP.h:
#pragma once
#include "resource.h" // main symbols
#include "MyInterface.h"
#include "_MyInterfaceEvents_CP.h"
using namespace ATL;
class ATL_NO_VTABLE CMyComServer :
public CComObjectRootEx<CComMultiThreadModel>,public CComCoClass<CMyComServer,&CLSID_MyInterfaceImpl>,public ISupportErrorInfo,public IConnectionPointContainerImpl<CMyComServer>,public CProxy_MyInterfaceEvents<CMyComServer>,public IdispatchImpl<MyInterface,&IID_MyInterface,&LIBID_MyInterfaceLibrary,1,0>,public IProvideClassInfo2Impl<&__uuidof(MyInterfaceImpl),&__uuidof(MyInterfaceEvents)>
{
public:
CMyComServer()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_MYINTERFACEIMPL)
DECLARE_CLASSFACTORY_SINGLetoN(CMyComServer)
BEGIN_COM_MAP(CMyComServer)
COM_INTERFACE_ENTRY(MyInterface)
COM_INTERFACE_ENTRY(Idispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
COM_INTERFACE_ENTRY(IProvideClassInfo)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CMyComServer)
CONNECTION_POINT_ENTRY(__uuidof(MyInterfaceEvents))
END_CONNECTION_POINT_MAP()
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
STDMETHOD(MyFunc1)(BSTR message);
};
OBJECT_ENTRY_AUTO(__uuidof(MyInterfaceImpl),CMyComServer);
这类似于我的 C++ ATL DCOM 服务的设置方式,这在我的测试中仍然有效。
MyComServer.cs:
using System;
using System.EnterpriseServices;
using System.Runtime.InteropServices;
using MyExample.Interop;
namespace MyExample
{
[ComVisible(true)]
[Guid("7A41F23E-B73A-40E4-A1B7-54B120B5923E")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(MyInterfaceEvents))]
[ProgId("MyExample.MyComServer")]
public class MyComServer : ServicedComponent,MyInterface,MyInterfaceEvents_Event
{
public event MyInterfaceEvents_MyEvent1EventHandler MyEvent1;
public void MyFunc1(string message)
{
MyEvent1?.Invoke("MyComServer: " + message);
}
}
}
这是我的 C# COM+ 服务不起作用。每当我尝试在下面的客户端中注册我的事件处理程序时,它都会给我这个错误:
An Exception was encountered: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'MyComClient,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName,String codeBase,Evidence assemblySecurity,RuntimeAssembly locationHint,StackCrawlMark& stackMark,IntPtr pPrivHostBinder,Boolean throwOnFileNotFound,Boolean forIntrospection,Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName,Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef,RuntimeAssembly reqAssembly,Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString,Boolean forIntrospection)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString,Boolean forIntrospection)
at System.Reflection.Assembly.Load(String assemblyString)
at System.Runtime.Serialization.FormatterServices.LoadAssemblyFromString(String assemblyName)
at System.Reflection.memberinfoserializationHolder..ctor(SerializationInfo info,StreamingContext context)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.SerializationInvoke(IRuntimeMethodInfo method,Object target,SerializationInfo info,StreamingContext& context)
at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj,StreamingContext context)
at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler,__BinaryParser serParser,Boolean fCheck,Boolean isCrossAppDomain,IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream,HeaderHandler handler,IMethodCallMessage methodCallMessage)
at System.EnterpriseServices.ComponentSerializer.UnmarshalFromBuffer(Byte[] b,Object tp)
at System.EnterpriseServices.ComponentServices.ConvertToMessage(String s,Object tp)
at System.EnterpriseServices.ServicedComponent.RemotedispatchHelper(String s,Boolean& Failed)
at System.EnterpriseServices.ServicedComponent.System.EnterpriseServices.IRemotedispatch.RemotedispatchNotAutodone(String s)
at System.EnterpriseServices.IRemotedispatch.RemotedispatchNotAutodone(String s)
at System.EnterpriseServices.RemoteServicedComponentProxy.Invoke(IMessage reqMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData,Int32 type)
at MyExample.Interop.MyInterfaceEvents_Event.add_MyEvent1(MyInterfaceEvents_MyEvent1EventHandler )
at MyExample.Program.Main(String[] args) in C:\Users\zzsupport\source\repos\MyExample\MyComClient\Program.cs:line 19
MyComClient.cs:
using System;
using MyExample.Interop;
namespace MyExample
{
class Program
{
static void Main(string[] args)
{
try
{
Type t = Type.GetTypeFromProgID(@"MyExample.MyComServer",true);
//Type t = Type.GetTypeFromProgID(@"MyExample.MyComServerCPP",true);
MyInterface instance = (MyInterface)Activator.CreateInstance(t);
MyInterfaceEvents_Event ev = (MyInterfaceEvents_Event)instance;
ev.MyEvent1 += Ev_MyEvent1;
System.Threading.Thread.Sleep(1000);
instance.MyFunc1("Hello?");
}
catch (Exception ex)
{
Console.WriteLine("An Exception was encountered: " + ex);
}
Console.WriteLine("Press Enter to continue...");
Console.ReadLine();
}
private static void Ev_MyEvent1(string message)
{
Console.WriteLine("Ev_MyEvent1: " + message);
}
}
}
我觉得我遗漏了一些明显的东西,但我还没有弄清楚。有什么建议吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)