8

更新:花了 20 多个小时试图让一个简单的示例正常工作后,我意识到这并不像看起来那么简单。像这样的文章揭示了“陷阱”——这是在 Windows 7 之前编写的(它以不同的方式处理清单)。我坚持通过 VSTO将 .NET 程序集公开给 VBA 。


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

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

但是,我想做免注册。

根据汉斯的建议更新:

我取消选中 Register for 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 并创建 Activation Context。进程监视器显示它访问 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。

4

1 回答 1

0

要使用免注册 COM,服务器(程序集)和客户端都需要位于同一文件夹中。看:

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

于 2013-03-19T15:25:20.743 回答