tags:

views:

1549

answers:

3

Hi all,

I need to make a piece of C# code interact through COM with all kinds of implementations.

To make it easeier for users of that integration, I included the interacted interfaces in IDL (as part of a relevant existing DLL, but without coclass or implementation), then got that into my C# code by running Tlbimp to create the types definition.

I implemented my C#, creating COM objects based on Windows registry info and casting the object into the interface I need.

I then created a C# implementation of the interface in a seperate project and registered it. The main program creates the testing COM object correctly but fails to cast it into the interface (gets a null object when using C# 'as', gets an InvalidCastException of explicit cast).

Can someone suggest why the interface is not identified as implemented by the testing object?

This is the interface defition in IDL (compiled in C++ in VS 2005):

    [
 object,
 uuid(B60C546F-EE91-48a2-A352-CFC36E613CB7),
 dual,
 nonextensible,
 helpstring("IScriptGenerator Interface"),
 pointer_default(unique)
]
interface IScriptGenerator : IDispatch{

 [helpstring("Init the Script generator")] 
  HRESULT Init();
 [helpstring("General purpose error reporting")] 
  HRESULT GetLastError([out] BSTR *Error);
};

This is the stub created for C# by Tlbimp:

[TypeLibType(4288)]
[Guid("B60C546F-EE91-48A2-A352-CFC36E613CB7")]
  public interface IScriptGenerator
  {
    [DispId(1610743813)]
    void GetLastError(out string Error);
    [DispId(1610743808)]
    void Init();
  }

This is part of the main C# code, creating a COM object by its ProgID and casting it to the IScriptGenerator interface:

public ScriptGenerator(string GUID)
{
  Type comType = Type.GetTypeFromProgID(GUID);
  object comObj = null;
  if (comType != null)
  {
    try
    {
      comObj = Activator.CreateInstance(comType);
    }
    catch (Exception ex)
    {
      Debug.Fail("Cannot create the script generator COM object due to the following exception: " + ex, ex.Message + "\n" + ex.StackTrace);
      throw ex;
    }
  }
  else
    throw new ArgumentException("The GUID does not match a registetred COM object", "GUID");

  m_internalGenerator = comObj as IScriptGenerator;
  if (m_internalGenerator == null)
  {
    Debug.Fail("The script generator doesn't support the required interface - IScriptGenerator");
    throw new InvalidCastException("The script generator with the GUID " + GUID + " doesn't support the required interface - IScriptGenerator");
  }

}

And this is the implementing C# code, to test it's working (and it's not):

  [Guid("EB46E31F-0961-4179-8A56-3895DDF2884E"),
  ProgId("ScriptGeneratorExample.ScriptGenerator"),
  ClassInterface(ClassInterfaceType.None),
  ComSourceInterfaces(typeof(SOAAPIOLELib.IScriptGeneratorCallback))]
  public class ScriptGenerator : IScriptGenerator
  {
   public void GetLastError(out string Error)
    {
      throw new NotImplementedException();
    }
    public void Init()
    {
      // nothing to do
    }
  }
A: 

Thanks for the quick reply.

I'm not sure I understand what 'implemented explicitly' means - the interface is declared and the methods as well. Isn't it 'explicit'?

Inbar Shani
A: 

I think you need this on the interface

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
Juan Zamudio
+1  A: 

Again - thanks for the suggestions.

I was able to finally resolve the issue on my own. I tried the above suggestions and didn't made any progress. Then I changed the namespace of the interop in the 'testing' code - it varied from the one in the main code because of different argument use when using Tlbimp. This solved the problem.

Here's my guess to why: .Net creates the COM object, but when it detects this is actually a .Net object, it bypass the COM layer and communicates directly. In which case, queryInterface (with the interface GUID) is not used and the interface do differ because of different C# namespaces.

This means that in order to supprot integration with .Net code, I will need to publish my original interop assembly aside the IDL.

Thanks, Inbar

Inbar Shani