Невозможно получить работающий без регистрации COM из VBA

ОБНОВЛЕНИЕ: Потратив более 20 часов на то, чтобы заставить работать простой пример, я понял, что это не так просто, как кажется. Подобные статьи раскрывают "ошибки" - и это было написано до Windows 7 (которая обрабатывает по-разному). Я придерживаюсь предоставления.NET сборок VBA через VSTO.


Я сделал простую сборку COM-Visible .NET и пытаюсь вызвать ее из Excel VBA. Если я "зарегистрируюсь для COM Interop" во время сборки.NET, я могу успешно вызвать его из VBA.

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

Тем не менее, я хочу сделать без регистрации.

Обновлено за совет от Ганса:

Я снял флажок Зарегистрироваться для COM Interop и установил для моего приложения значение.

<?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 и создает контекст активации. Монитор процессов показывает, что он обращается к 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.

1 ответ

Чтобы использовать COM без регистрации, и сервер (сборка), и клиент должны находиться в одной папке. Увидеть:

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

Другие вопросы по тегам