views:

583

answers:

5

Ok, I'm going crazy. I've been trying to make a simple .net assembly visible to use as a COM object but it's not working. I've been trying a lot of different aproaches but none of them work. So far the closest i've got is the one with the least amount of attributes, interfaces, manually registering etc.

I have a vbscript as a test which looks like this:

Dim o
o = CreateObject("MyNamespace.MyClass")
msgbox o.Test()

My c# code looks like this:

using System;
using System.Runtime.InteropServices;
namespace MyNamespace 
{
  [ProgId("MyNamespace.MyClass")]
  public class MyClass
  {
    public string Test()
    {
       return "teststring";
    }
  }
}

On my project (VS2008) i've selected 'Make assembly COM visible' - which added an attribute to my AssemblyInfo.cs and i also checked 'Register for COM interop'.

I Can see that the ProgId really makes no difference (in my case anyways) - as long as i specify the real namespace+classname, i can however override it which i guess is nice.

The problem is - my CreateObject goes well, but the method Test() can not be found. In fact if i take the dll and extract the tlb and expect that i see no methods at all.

The error i get is this:

C:\inetpub\wwwroot\ASPTest\testrun.vbs(3, 1) Microsoft VBScript runtime error: Object doesn't support this property or method: 'Test'

I'd love any feedback, but just to let you know what i've been trying. I've messing around with Guid and AttributeGuid on the class, defining the COMVisible explicitly on the class as well i tried NOT registering for COM interop and instead did regasm /codebase /regfile.

One last note - most my testing has revolved around a non-signed assembly, but trying to pinpoint the error i tried with a strongname/key as well but it didn't do anything.

Can anyone help me find the problem, please?

A: 

Don't you need to define some interface that has the methods, and implement that interface?

Ganesh Sittampalam
I'm pretty sure i don't have to because i've seen it work without - that was with the regasm /codebase /regfile and then running the regfile. But if you got an example getting it to work with defining an explicit interface i'd be glad to see it :)
Per Hornshøj-Schierbeck
+2  A: 

Did i mention i run Windows 7 RC 64 bit?

Well i think that might explain my VS isn't doing it right: http://kbalertz.com/956933/Issues-building-project-assembly.aspx It seems VS uses the 32bit version of registry and not the 64bit...

Per Hornshøj-Schierbeck
Hrm i think the project is built 32 bit and hence it's ok for VS to register it in the 32 bit section...
Per Hornshøj-Schierbeck
Sounds more like an oversight to me. There is no reason why VS although being 32 bit couldn't spin up a 64 bit version of system32/regsvr32 to register the tlb in the 64 bit part of the hive. It would have made sense either to add such a choice to the UI or use the CPU target value of build to decide which or both hive sections to register in.
AnthonyWJones
Anthony: That is true - it should.
Per Hornshøj-Schierbeck
A: 

This works for me:

using System;
using System.Runtime.InteropServices;
namespace MyNamespace
{

    [GuidAttribute("8DDE02DF-B31C-4d91-98A7-C64444701985")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class clsCOMWraper
    {
       public string Test()
      {
         return "teststring";
      }
    }
}

Thse assembly must be signed.

The, register with regasm /codebase

Note however that using AutoDual on ClassInterface is strongly discouraged it could lead older early binding clients to call the wrong methods.
AnthonyWJones
I tried this, and now it won't even create the object - it fails on the CreateObject() line instead. I double checked the Namespace.Class is correct - or atleast the same...
Per Hornshøj-Schierbeck
A sidenote - whenever i add the GuidAttribute the CreateObject fails when trying to create the object, once i remove it - i can get as far as to trying to call a method (that it can't find - like the error i posted)
Per Hornshøj-Schierbeck
+1  A: 

I started from the beginning and removed anything regarding COM interop on my project, i then added

[Guid(...some guid...)]
[ComVisible(true)]

on MyClass and i added a strongname (used the project setting to set it - instead of defining it in the AssemblyInfo.cs.

When i compiled the assembly, i copied the files to another location where i did a

regasm MyNamespace.MyClass.dll /codebase /regfile

Then i ran and accepted the registry entry.

This made it work - whenever i make changes i just recompile and copy the files over the old (no unregistering) and then i only do:

regasm MyNamespace.MyClass.dll /codebase

... and that's it - changes i made to MyClass are imediately visible in my vbscript and in my asp page.

Per Hornshøj-Schierbeck
A: 

I dont see any constructor for the Class. COM Interop needs a default constructor (without any params) for it to generate a COM interface successfully.

Try adding a constructor and see if it works.

The .net framework will provide it with a default empty contructor if i don't supply one. I did try it though, but also my resharper plugin grays it out, implying that declaring it is redundant.
Per Hornshøj-Schierbeck