UPDATE:. After spending 20+ hours trying to get a simple work example, I realized that it is not as simple as it seems. Articles like this reveal "gotchas" - and it was written before Windows 7 (which treats manifests differently). I adhere to exposing .NET assemblies for VBA through VSTO .
I made a simple assembly of COM-Visible.NET and am trying to call it from Excel VBA. If I "register for COM interoperability" during my .NET assembly, I can successfully call it from VBA.
Sub VBA() Dim obj As Object Set obj = actCtx.CreateObject("ComTest.Main") MsgBox obj.Test() '<-- Displays "Hello" End Sub
However, I want to do a free registration.
Updated for advice from Hans:
I unchecked the Register for COM Interop checkbox and installed the app.Manifest application:
<?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>
I created a dummy "client.manifest" as follows:
<?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>
I changed my VBA to use client.manifest when creating my object:
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
It does not work in CreateObject with the less useful error Method 'CreateObject' of object 'IActCtx' failed .
sxstrace shows that it reads client.manifest and creates an activation context. Process Monitor indicates that it is accessing ComTest.dll and is looking for a registry for class 975DC7E0-4596-4C42-9D0C-0601F86E3A1B.
What am I missing?
Here is the .NET code:
<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
I am running 64-bit Windows 7.