2

I've created a ComVisible-class:

[Guid("73a3f91f-baa9-46ab-94b8-e526c22054a4"), ComVisible(true)]
public interface ITest
{
    void Foo();
}

[Guid("99f72d92-b302-4fde-89bb-2dac899f5a48"), ComVisible(true)]
public class Class1 : ITest
{
    public void Foo() { }
}

and registered it via

regasm ComClassTest.dll /tlb:ComClassTest.tlb

into the registry. When I try to call it in my Silverlight 4 out-of-browser, elevated trust application like this:

var foo = AutomationFactory.CreateObject("ComClassTest.Class1");

I get an exception "{System.Exception: Failed to create an object instance for the specified ProgID."

However, I am able to call AutomationFactory.CreateObject("Word.Application") without an Exception and to call Activator.CreateInstance(Type.GetTypeFromProgID("ComClassTest.Class1")) in a normal C#-console application if I copy the ComClassTest.dll into the bin-directory.

What have I forgotton?

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
Papa Mufflon
  • 17,558
  • 5
  • 27
  • 35

1 Answers1

0

First thing to do is test that you can create the object from somewhere else such as VBScript. Create a .vbs file with the content:-

o = CreateObject("ComClassTest.Class1")

If that doesn't generate an error then there is something specifically that SL OOB is upset with otherwise your problem isn't really related to Silverlight at all.

Consider making the following changes to your COM code.

  • Its often easier to specify ComVisible(true) at the assembly level. You can do that from the application tab of the project properties on the Assembly Information dialog. You can also get Visual Studio to register the assembly with COM and build time using the option found on the build tab of the project properties.

  • Its a good idea to be specific about the ComInterfaceType you want to expose.

  • Things get really messy if you expose the class interface directly generally you only want the interface you have defined to be used and that this be the default interface for the class. In addition it probably better to stick to COM naming conventions for the default interface of a class.

  • Finally (and possibly crucially in your case) its a good idea to be explicit about the ProgId to use for the class.

Applying the above and we get:-

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("73a3f91f-baa9-46ab-94b8-e526c22054a4")]
public interface _Class1
{
    void Foo();
}

[ClassInterface(ClassInterfaceType.None)] 
[Guid("99f72d92-b302-4fde-89bb-2dac899f5a48")]
[ProgId("ComClassTest.Class1")]
public class Class1 : _Class1
{
    public void Foo() { }
}
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • I've done all your suggestions, but the exception is still the same. As mentioned above, I can call the assembly from a C#-console application - doesn't that prove that it's a Silverlight problem? – Papa Mufflon Dec 18 '10 at 19:08
  • @Papa: The C# Console app is not using the `IDispatch` OLE Automation interface that a the Silverlight code is attempting to use. Is that single line of VBScript in my answer successful? – AnthonyWJones Dec 18 '10 at 22:11
  • Im having the same problem; tested your vbs script (running in bin/Debug/ of DLL project) but it gives me: line 1, char 1: The system cannot find the file specified. A C# console app using Activator as described by Papa.. works fine. I've got ComVisible at assembly level. – gauteh Jan 15 '11 at 18:43
  • Changing your script to: Set o = CreateObject("Sapi.SpVoice") works fine however.. So the problem seems to be with Automation and registering it ? – gauteh Jan 15 '11 at 19:02
  • @Gauteh: Yes you're right my script should have a `Set`, I'm always forgetting that VB quirk. I can't think why the VBScript would work but `AutomationFactory` would fail. – AnthonyWJones Jan 15 '11 at 21:10
  • I noticed that the VB script works, even with my Com Dll, if I copy the Dll to windows\system32\ (regasm run on dll in project folder). However the Silverlight app still fails. I suspect the problem is that it does not find the Dll - but can't figure out where to put it, or what to modify the registry to. Currently using a different approach with Dll -> WCF Service -> Windows Service, but COM would cut some layers. – gauteh Jan 16 '11 at 00:54