tags:

views:

65

answers:

3

I have two separate projects (comclient and comserver), with some very simple code:

comserver/Program.cs

using System;
using System.Reflection;
using System.Runtime.InteropServices;

namespace comserver
{
  class Program
  {
    static void Main(string[] args)
    {
      RegisterComObject();
    }

    public static void RegisterComObject()
    {
      Assembly asm = Assembly.GetExecutingAssembly();
      RegistrationServices reg = new RegistrationServices();
      bool f = reg.RegisterAssembly(asm, AssemblyRegistrationFlags.SetCodeBase);
      Console.WriteLine("RegisterAssembly: {0}", f ? "ok" : "fail");
    }
  }

  [ComVisible(true)]
  [Guid("49752A5D-4CAD-495f-A220-07B60CDB6CE8")]
  interface IComServerDemo
  {
    void SayHello(string name);
  }

  [ComVisible(true)]
  [Guid("8FDB8319-6EC3-45b4-A384-1403D3993A07")]
  public class ComServerDemo : IComServerDemo
  {
    public void SayHello(string name)
    {
      Console.WriteLine("Hello {0}!", name);
    }
  }
}

comclient/Program.cs

using System;
using System.Runtime.InteropServices;

namespace comclient
{
  class Program
  {
    static void Main(string[] args)
    {
      ComServerDemo csdObj = new ComServerDemo();
      IComServerDemo csd = (IComServerDemo)csdObj;
      csd.SayHello("Bob");
    }
  }

  [ComImport, Guid("8FDB8319-6EC3-45b4-A384-1403D3993A07")]
  public class ComServerDemo
  {
  }

  [ComImport, Guid("49752A5D-4CAD-495f-A220-07B60CDB6CE8")]
  interface IComServerDemo
  {
    void SayHello(string name);
  }
}

When I run comserver.exe, it registers the COM interface OK:

RegisterAssembly: ok

But when I try to run the COM client, I get this exception:

An unhandled exception of type 'System.InvalidCastException' occurred in comclient.exe

Additional information: Unable to cast object of type 'comserver.ComServerDemo' to type 'comclient.ComServerDemo'.

Any ideas why I'm getting this exception? The comclient project does not reference the comserver class. Also, I'm trying to create an out of proc COM server, but I have a feeling this might not do the trick - any ideas about this also?

A: 

Well, you don't show us comclient, so I just have to guess, but I'll assume you define a class called ComServerDemo in comclient (defined identically to the one in comserver)

But identically definitions is not the same as being the same type.

UPDATE (now that you posted comclient)

Try putting your definitions of ComServerDemo & IComServerDemo in your comclient class, into the comserver namespace.

using System; 
using System.Runtime.InteropServices; 

namespace comclient 
{ 
  class Program 
  { 
    static void Main(string[] args) 
    { 
      ComServerDemo csdObj = new ComServerDemo(); 
      IComServerDemo csd = (IComServerDemo)csdObj; 
      csd.SayHello("Bob"); 
    } 
  } 
}
namespace comserver
{ 
  [ComImport, Guid("8FDB8319-6EC3-45b4-A384-1403D3993A07")] 
  public class ComServerDemo 
  { 
  } 

  [ComImport, Guid("49752A5D-4CAD-495f-A220-07B60CDB6CE8")] 
  interface IComServerDemo 
  { 
    void SayHello(string name); 
  } 
}
James Curran
+2  A: 

You need a feature called 'Type equivalence', added to .NET 4.0. It is used to allow two distinct .NET types to be considered equivalent when they have the exact same GUID. This feature was used to implement the new 'Embed Interop Types' feature, making it unnecessary to deploy PIAs.

I don't know enough about it to judge whether you can actually use it to make this code work. Gut instinct says yes. Check out the docs for the [TypeIdentifier] attribute.

Hans Passant
+1  A: 

It doesn't appear that you have anything relating this section of code:

  ComServerDemo csdObj = new ComServerDemo();  
  IComServerDemo csd = (IComServerDemo)csdObj;  

In the server class you have ComServerDemo : IComServerDemo, but in the client you don't have this relationship. Attempting this cast should fail because the compiler won't see the connection.

Edit: In agreement with @Hans Passant on type equivalence, you have redefined (re: undefined) the relationship so the type equivalence no longer holds.

Joel Etherton