2013-03-19 56 views
2

UPDATE:花了20多个小时试图获得一个简单的示例工作后,我意识到这并不像看起来那么简单。文章like this揭示了“陷阱” - 这是在Windows 7之前编写的(它以不同方式处理清单)。我坚持将.NET程序集暴露给VBA via VSTO无法免费注册COM从VBA工作


我做了一个简单的COM-Visible .NET程序集,并试图从Excel VBA中调用它。如果我在.NET构建期间“注册COM Interop”,我可以成功从VBA调用它。

Sub VBA()  
    Dim obj As Object 
    Set obj = actCtx.CreateObject("ComTest.Main") 
    MsgBox obj.Test() '<-- Displays "Hello" 
End Sub 

但是,我想免费注册。

每提醒更新从汉斯:

我未选中注册为COM Interop,我app.Manifest设置为:

<?xml version="1.0" encoding="utf-8"?> 
<asmv1:assembly 
    manifestVersion="1.0" 
    xmlns="urn:schemas-microsoft-com:asm.v1" 
    xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" 
    xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    <assemblyIdentity 
    type="win32" 
    version="1.0.0.0" 
    name="ComTest" 
    publicKeyToken="a36a7110110d7bd7" /> 

    <clrClass 
     clsid="{975DC7E0-4596-4C42-9D0C-0601F86E3A1B}" 
     progid="ComTest.Main" 
     threadingModel="Both" 
     name="ComTest.Main" 
     runtimeVersion="v4.0.30319"> 
    </clrClass> 

    <file name = "ComTest.dll"></file> 
</asmv1:assembly> 

我创建了一个虚拟 “client.manifest” 是这样的:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<asmv1:assembly 
    manifestVersion="1.0" 
    xmlns="urn:schemas-microsoft-com:asm.v1" 
    xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" 
    xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

    manifestVersion="1.0" 
    xmlns="urn:schemas-microsoft-com:asm.v1" > 
    <assemblyIdentity 
     name="xxx" 
     version="1.0.0.0" /> 
    <dependency> 
     <dependentAssembly> 
      <assemblyIdentity 
       type="win32" 
       name="ComTest" 
       version="1.0.0.0" 
       publicKeyToken="a36a7110110d7bd7" /> 
     </dependentAssembly>    
    </dependency> 
</asmv1:assembly> 

我修改了VBA创建我的对象时使用client.manifest:

Sub VBA()  
    Dim actCtx As Object 
    Set actCtx = CreateObject("Microsoft.Windows.ActCtx") 
    actCtx.Manifest = "C:\Users\me\Desktop\COM Test\ComTest\ComTest\bin\Debug\client.manifest" 

    Dim obj As Object 
    Set obj = actCtx.CreateObject("ComTest.Main") '<-- Fails here. 
    MsgBox obj.Test()  
End Sub 

它在CreateObject上失败,并且出现的错误号为Method 'CreateObject' of object 'IActCtx' failed

sxstrace显示它读取client.manifest并创建激活上下文。 Process Monitor显示它访问ComTest.dll并在注册表中搜索975DC7E0-4596-4C42-9D0C-0601F86E3A1B。

我错过了什么?


这里的.NET代码:

<ComVisible(True)> 
<Guid("EB6AA207-ECC7-413B-9A9B-9D142FF2701D")> 
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> 
Public Interface IMain 
    Function Test() As String 
End Interface 

<ComVisible(True)> 
<Guid("975DC7E0-4596-4C42-9D0C-0601F86E3A1B")> 
<ProgId("ComTest.Main")> 
<ClassInterface(ClassInterfaceType.None)> 
<ComDefaultInterface(GetType(IMain))> 
Public Class Main 
    Implements IMain 
    Public Function Test() As String Implements IMain.Test 
     Return "HELLO" 
    End Function 
End Class 

我运行64位Windows 7

+0

使用clrClass而不是comClass。 – 2013-03-20 00:32:07

回答

0

要使用免注册COM,服务器(组装)和客户端需要位于同一个文件夹中。参见:

http://msdn.microsoft.com/en-us/magazine/cc188708.aspx

+0

即使我将所有内容复制到我的Office12文件夹(EXCEL.exe所在的位置)并从此处运行,我也会得到该错误。 – nunzabar 2013-03-19 15:37:11

+0

哦,我错过了你试图从VBA中使用它。好吧,我不认为你可以在这种情况下使免注册的COM工作,因为这需要为Excel创建一个应用程序清单。另外,将东西复制到应用程序的安装文件夹似乎不是一个好主意。我认为无reg的COM是为了便于部署而设计的,当你是服务器和客户端的开发者时,但当客户端不了解服务器时,它不能很好地工作,因为客户端需要引用服务器在其应用程序清单中。 – user1610015 2013-03-19 16:00:25

相关问题