Skip to content

Cannot run Samples, any configuration #1

@edvinkuric

Description

@edvinkuric

Hello, i have trouble running any of the provided examples.

I get the following Exception, when using net481:
InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to class type 'Grasshopper.Plugin.GH_RhinoScriptInterface'.

When using dotnetcore 7, i can't even load the correct DLLs or receive an "Error: HResult E_Fail has been returned from a call to a COM component", which i can't debug further.

Are there any restrictions on using specific versions?

My setup is:

  • current Visual Studio 2022 Community Edition (17.10)
  • both dotnet 481 and dotnet core 7 (dotnet core 8 is also installed, but didn't try that)
  • both Rhino 7 and 8 are installed
  • nuget-packages: .NET481: RhinoCommon + Grasshopper 7.36.23346.16351 (with custom RhinoInside-Resolver as well as the nuget-package with version 7.0.0), ; dotnetcore7: RhinoCommon + Grasshopper 8.7.24138.15431 (with custom RhinoInside-Resolver)
  • both Rhino-Versions are licensed and can be opened
  • Grasshopper is installed as Plugin
  • GH-Script is added as embedded Resource
  • Tried with Resolver-Flag "UseLatest" set to either true or false.

Ideally, i can run Rhino 8 Headless with dotnetcore 7 to be "future-proof", but i hadn't any luck for now.
I would also be happy, if i can run any variant for starters, but no Rhino 7 Licenses can be bought anymore.

Can somebody help me with that or provide suggestions? That would be awesome - any hint helpsp

Here is the code, which i used/changed:

Program.cs: (adapted part)
`
namespace RhinoGrassHopperRunner
{
class Program
{

    static Program()
    {
        RhinoInside.Resolver.Initialize();
        Console.WriteLine("Initializing RhinoInside.Resolver");
    }

    static void Main(string[] args)
    {
        using (var core = new Rhino.Runtime.InProcess.RhinoCore())
        {
            RunHelper();
        }
    }

    // Currently need a separate RunHelper function so the .NET runtime won't attempt to load the
    // Grasshopper assembly until after RhinoCore has been created. This should be "fixable" in a
    // future version of the RhinoInside nuget package
    static void RunHelper()
    {
     // Extract definition to sample location as executable
     var assembly = typeof(Program).Assembly;
     string dir = System.IO.Path.GetDirectoryName(assembly.Location);
     var scriptName = "DXF2RVT.gh";
     string filePath = System.IO.Path.Combine(dir, scriptName);
    
     using (var resStream = assembly.GetManifestResourceStream("RhinoGrassHopperRunner." + scriptName))
     using (var outStream = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
     {
         resStream.CopyTo(outStream);
     }
    var plugins = Rhino.PlugIns.PlugIn.GetInstalledPlugIns().OrderBy(x => x.Value);
    Console.WriteLine("plugins:", plugins.Select(x => x.Key + "  " + x.Value));
    // Start grasshopper in "headless" mode
    var plugin = plugins.FirstOrDefault(x => x.Value.Contains("Grasshopper")).Key;
    //if (string.IsNullOrEmpty(plugin))
    //{
    //    Console.WriteLine("Grasshopper not found");
    //    return;
    //}
    var pluginObject = Rhino.RhinoApp.GetPlugInObject(plugin);
    var type = pluginObject.GetType();
    var castedObject = (Grasshopper.Plugin.GH_RhinoScriptInterface)pluginObject;
    castedObject.RunHeadless();
    ....

`

Resolver.cs:

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

// Code from https://github.com/mcneel/compute.rhino3d/blob/8.x/src/compute.geometry/Resolver.cs
namespace RhinoInside
{
public class Resolver
{
///


/// Set up an assembly resolver to load RhinoCommon and other Rhino
/// assemblies from where Rhino is installed
///

public static void Initialize()
{
Console.WriteLine("Initializing RhinoInside.Resolver");
if (System.IntPtr.Size != 8)
throw new Exception("Only 64 bit applications can use RhinoInside");
AppDomain.CurrentDomain.AssemblyResolve += ResolveForRhinoAssemblies;
}

    static string _rhinoSystemDirectory;

    /// <summary>
    /// Directory used by assembly resolver to attempt load core Rhino assemblies. If not manually set,
    /// this will be determined by inspecting the registry
    /// 
    /// This is the C:/Program Files/Rhino 8/System directory on Windows
    /// This is the Rhinoceros.app/Contents/Frameworks directory on Mac
    /// </summary>
    public static string RhinoSystemDirectory
    {
        get
        {
            //return "C:\\Program Files\\Rhino 7\\System";
            // THIS USES THE RHINO 8 DIRECTORY
            if (string.IsNullOrWhiteSpace(_rhinoSystemDirectory))
                _rhinoSystemDirectory = FindRhinoSystemDirectory(); 
            return _rhinoSystemDirectory;
        }
        set
        {
            _rhinoSystemDirectory = value;
        }
    }

    /// <summary>
    /// Whether or not to use the newest installation of Rhino on the system. By default the resolver will only use an
    /// installation with a matching major version.
    /// </summary>
    public static bool UseLatest { get; set; } = true; // was true to use rhino8

    public static string AssemblyPathFromName(string systemDirectory, string name)
    {
        if (name == null || name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
            return null;

        // load Microsoft.macOS in the default context as xamarin initialization requires it there
        if (name == "Microsoft.macOS")
            return null;

        //if (name.Contains("Rhino") || name.Contains("Grasshopper"))
        //{
            name = name.Split(',')[0];
        //}
        if (name.Contains("Grasshopper"))
        {
            systemDirectory = "C:\\Program Files\\Rhino 7\\Plug-ins\\Grasshopper";
        }
        else if(name.Contains("Rhino") && systemDirectory == null)
        {
            systemDirectory = "C:\\Program Files\\Rhino 7\\System";
        }
        string path = null;
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            path = Path.Combine(systemDirectory, "RhCore.framework/Resources", name + ".dll");
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            //path = Path.Combine(systemDirectory, "netcore", name + ".dll");
            if (!File.Exists(path))
            {
               path = Path.Combine(systemDirectory, name + ".dll");
            }
            if (!File.Exists(path))
            {
                var intPath = typeof(int).Assembly.Location;
                string directory = System.IO.Path.GetDirectoryName(intPath);
                path = Path.Combine(directory, name + ".dll");
                if (!File.Exists(path) || name.Contains(".Drawing") || name.Contains("WindowsBase"))
                {
                    int index = directory.IndexOf("NETCORE", StringComparison.OrdinalIgnoreCase);
                    directory = directory.Substring(0, index) + "WindowsDesktop" + directory.Substring(index + "NETCORE".Length);
                    path = Path.Combine(directory, name + ".dll");
                }
            }
        }
        return path;
    }

    static Assembly ResolveForRhinoAssemblies(object sender, ResolveEventArgs args)
    {
        string path = AssemblyPathFromName(RhinoSystemDirectory, args.Name);
        //// remove everything after first occurrence of ,
        //var cleanedName = path.Split(',');

        //path = cleanedName[0] + ".dll";

        if (File.Exists(path))
            return Assembly.LoadFrom(path);
        return null;
    }

    static string FindRhinoSystemDirectory()
    {
        var major = Assembly.GetExecutingAssembly().GetName().Version.Major;

        if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
        {
            string baseName = @"SOFTWARE\McNeel\Rhinoceros";
            using var baseKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(baseName);
            string[] children = baseKey.GetSubKeyNames();
            Array.Sort(children);
            string versionName = "";
            for (int i = children.Length - 1; i >= 0; i--)
            {
                // 20 Jan 2020 S. Baer (https://github.com/mcneel/rhino.inside/issues/248)
                // A generic double.TryParse is failing when run under certain locales.
                if (double.TryParse(children[i], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double d))
                {
                    if (d < 8.0)
                        continue;

                    versionName = children[i];

                    if (!UseLatest && (int)Math.Floor(d) != major)
                        continue;

                    using var installKey = baseKey.OpenSubKey($"{versionName}\\Install");
                    string corePath = installKey.GetValue("CoreDllPath") as string;
                    if (System.IO.File.Exists(corePath))
                    {
                        return System.IO.Path.GetDirectoryName(corePath);
                    }
                }
            }
        }

        return null;
    }
}

}
`
.csproj:
image

Thank you very much!!
BR, Edvin

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions