我目前正在尝试让Excel作为客户端,使用.NET DLL作为服务器,实现无需注册即可使用的COM。目前我只是想试验一下,但遇到了一些问题。
显然,由于我正在使用Excel,所以我不能简单地将客户端清单与可执行文件放在一起,因此我正在使用Microsoft.Windows.ActCtx。
我在同一位置拥有客户端清单、程序集清单和DLL。
不幸的是,C#中有效的方法在Excel / VBA中似乎不起作用,我对原因感到困惑。虽然C#测试客户端工作得非常好,但VBA会出现80070002错误,并显示消息Method 'CreateObject' of object 'IActCtx' failed。
我有一个.NET DLL(COMTestService.dll),将单个类/接口暴露给COM(COMTestObject
/ ICOMTestObject
),如下所示:
[ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("EEE50CDF-D8EC-4F38-B986-C231EC45171E")]
public interface ICOMTestObject
{
[ComVisible(true)]
string GetString(int number);
}
[ComVisible(true), ClassInterfaceAttribute(ClassInterfaceType.None), ComDefaultInterface(typeof(ICOMTestObject))]
[Guid("6E54611B-8B56-49E0-9415-E59B0774A4BE")]
public class COMTestObject : ICOMTestObject
{
public COMTestObject()
{
}
public string GetString(int number)
{
return string.Format("The number is: {0}", number);
}
}
客户端清单(COMTestService_Client.manifest):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
manifestVersion="1.0"
xmlns="urn:schemas-microsoft-com:asm.v1" >
<assemblyIdentity
name="client"
version="1.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity
name="COMTestService"
version="1.0.0.0"
processorArchitecture="msil" />
</dependentAssembly>
</dependency>
</assembly>
程序集清单(COMTestService.manifest):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
manifestVersion="1.0"
xmlns="urn:schemas-microsoft-com:asm.v1" >
<assemblyIdentity
name="COMTestService"
version="1.0.0.0"
processorArchitecture="msil" />
<clrClass
clsid="{6E54611B-8B56-49E0-9415-E59B0774A4BE}"
progid="COMTestService.COMTestObject"
threadingModel="Both"
name="COMTestService.COMTestObject"
runtimeVersion="v4.0.30319">
</clrClass>
<file
name="COMTestService.dll"
hashalg="SHA1">
</file>
</assembly>
VBA客户端代码:
Dim actCtx As Object
Set actCtx = CreateObject("Microsoft.Windows.ActCtx")
actCtx.Manifest = "...\COMTestService_Client.manifest"
Dim testObject As Object
Set testObject = actCtx.CreateObject("COMTestService.COMTestObject") 'This line throws...
Dim text As String
text = thing.GetString(42)
Debug.Print text
C#客户端代码:
var actCtxType = System.Type.GetTypeFromProgID("Microsoft.Windows.ActCtx");
dynamic actCtx = System.Activator.CreateInstance(actCtxType);
actCtx.Manifest = @"...\COMTestService_Client.manifest";
var type = System.Type.GetTypeFromProgID("COMTestService.COMTestObject");
dynamic obj = System.Activator.CreateInstance(type);
dynamic s = obj.GetString(42);
编辑
情况越来越复杂了… 仅仅是为了好玩,我写了一个快速创建COM对象的C#帮助类,并将它注册成可见的,然后通过 public object CreateObject(string manifestPath, string typeName)
这样的方法将其传递回去。调用这个方法在C# exe中可以正常工作,但在VBA中调用失败了(80070002,消息:The system cannot find the file specified.)。现在我更加困惑了…
非常感谢任何帮助,如果需要提供更多信息,请告诉我,我会很乐意提供!