Cannot do anything with Rhino 6 COM objects

I am trying to automate Rhino 6 via COM:

var t = Type.GetTypeFromProgID("Rhino.Interface");
dynamic com = Activator.CreateInstance(t); // Works, launches Rhino
var rhino = (IRhinoInterface)com; // InvalidCastException

I’m able to launch Rhino fine. But I can’t figure out how to use the returned COM object to actually do anything. If I try to cast it to any of the types in the provided .tlb, I get an InvalidCastException: “Unable to cast COM object of type ‘System.__ComObject’ to interface type ‘Rhino.IRhinoInterface’”. If I leave it as dynamic and try to use properties/methods directly (e.g. the ones in samples from Rhino 6 COM Interface and Fail to get IRhinoApplication from COM Object in Rhino 6), I get RuntimeBinderExceptions with messages like "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ‘‘System.__ComObject’ does not contain a definition for ‘GetScriptObject’’.

I’ve tried all the combinations of ProgIDs in https://developer.rhino3d.com/api/rhinoscript/introduction/external_access.htm and types in the type library, and I see this no matter which pair I pick. Is there some obvious thing I’m missing?

Check this example

Sorry, I wasn’t clear. When I do that, IsInitialized() throws a RuntimeBinderException.

Sorry, my bad - I did not read to the end when I saw you trying to use Rhino.Interface. I’ve checked our codebase and when you say

I get RuntimeBinderExceptions with messages like "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ‘‘System.__ComObject’ does not contain a definition for ‘GetScriptObject’’.

we find the same problem, which is that GetScriptObject is not COM-enabled. If you try other methods, like RunScript or GetPluginObject, those should work, in combination with "Rhino.Application" as prog-id and leaving it as a dynamic type.

Neither of those combinations work, I have the same problem. As I said, I have this problem for every pair of methods/ProgIds I found in any of the linked examples. I was just using Rhino.Interface/GetScriptObject as an example.

Here is some specific code with the same problem:

var t = Type.GetTypeFromProgID("Rhino.Application");
dyamic com = Activator.CreateInstance(t);
com.RunScript("Point 1,1,1");

(I don’t know if that’s the right way to use RunScript but there’s no method found at all.)

I got the following to work, but the outcome is that neither IRhinoInterface nor IRhinoApplication can be used on the dynamic object.

The C# project should COM-import the Rhino-6 and RhinoScript-6 COM libraries.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Rhino;

namespace AutoRhino
{
  class Program
  {
    static void Main(string[] args)
    {
      dynamic _rhino;
      try
      {
        const string rhinoId = "Rhino.Application";
        Type type = Type.GetTypeFromProgID(rhinoId);
        _rhino = Activator.CreateInstance(type);// as IRhinoApplication;

      }
      catch (Exception e)
      {
        Console.WriteLine("Error creating COM instance, {0}", e);
        return;
      }


      string className = _rhino.GetType().ToString();
      Console.WriteLine("Rhino type: " + className);

      // Wait until Rhino is initialized before calling into it
      const int bailMilliseconds = 15 * 1000;
      int timeWaiting = 0;
      while (0 == _rhino.IsInitialized())
      {
        Thread.Sleep(100);
        timeWaiting += 100;
        if (timeWaiting > bailMilliseconds)
        {
          Console.WriteLine("Rhino initialization timed out: Failed");
          return;
        }
      }

      Console.WriteLine("RhinoCom Initialisation took {0} ms.", timeWaiting);
      _rhino.Visible = 1;

      if (_rhino is IRhinoApplication app)
      {
        app.RunScript("Point 1,1,1 _Enter", 0);
      }
      else if (_rhino is IRhinoInterface iface)
      {
        iface.RunScript("Point 2,2,2 _Enter", 0);
      }
      else
      {
        //this is what gets called
        _rhino.RunScript("Point 3,3,3 _Enter", false);
      }



      while (true)
        Thread.Sleep(100);
    }
  }
}

That program doesn’t work for me. As expected:

Rhino type: System.__ComObject
Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.__ComObject' does not contain a definition for 'IsInitialized'

at the call to IsInitialized().

Ok, that is weird. I don’t think I can help you further. Maybe @dale of @stevebaer can help.

Hi @rosecodym,

The sample reference above seems to work here. For COM to work, entries in the Registry must be set correctly. So, you might consider repairing your Rhino installation via Control Panel (Programs and Features), to ensure these settings are correct.

– Dale

Installation repair didn’t fix it. Are there any particular registry entries I can check?

Hi @rosecodym,

Before we start digging into the Registry, do you have some sample code that we can run here? I just want to rule out someting simple before we get carried away.

Thanks,

– Dale

I just checked something on a hunch - my application was targeting .NET Core. I switched it to .NET Framework and it worked. Bummer that I can’t use the type library though.