Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RegFree COM working from C#, NOT working from VBA

I'm curently trying to get registration-free COM working with Excel as the client, and a .NET dll as the server. Currently I'm simply trying to get a proof-of-concept working but am having trouble.

Obviously, as I am using Excel, I can't simply use a client manifest living alongside the executable, so I'm using Microsoft.Windows.ActCtx (link)

I have the client manifest, assembly manifest, and dll all in the same location.

Unfortunately, what works in C# doesn't appear to work in Excel / VBA and I'm stumped as to the reason. While the C# test client works perfectly, VBA gives a 80070002 error, with message Method 'CreateObject' of object 'IActCtx' failed.

I have a .NET dll (COMTestService.dll) exposing a single class / interface to COM (COMTestObject / ICOMTestObject ), as here:

[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);
    }
}

The client manifest (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>

The assembly manifest (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>

The VBA client code:

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

The C# client code:

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);

EDIT

The plot thickens... Just for fun, I wrote a quick COM-visible, REGISTERED helper class to do the object creation in C#, then pass it back, using a method along the lines of public object CreateObject(string manifestPath, string typeName) Now, calling this from a C# exe works fine, but calling it from VBA fails (80070002 again, message: The system cannot find the file specified.). Now I'm even more confused...

Thanks in advance for any help, and if I need to supply any more info just let me know and I'll be glad to oblige!

like image 764
Simon Cowen Avatar asked Mar 21 '12 13:03

Simon Cowen


1 Answers

Using Process Monitor, I discovered that the dll was being searched for in C:/Program Files/Microsoft Office/Office11/. I moved all my dlls over into there and the error was gone.

On a sidenote, if anybody knows how to tell Excel not to look there for my files but instead where the .tlb was found, I'm interested. (I already tried adding the path to the PATH environment variable)

like image 71
sean.net Avatar answered Sep 29 '22 01:09

sean.net