Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot run Samples, any configuration #1

Open
edvinkuric opened this issue Jun 12, 2024 · 1 comment
Open

Cannot run Samples, any configuration #1

edvinkuric opened this issue Jun 12, 2024 · 1 comment

Comments

@edvinkuric
Copy link

edvinkuric commented Jun 12, 2024

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

@galer7
Copy link
Owner

galer7 commented Jun 21, 2024

Hey Edvin, just seeing your message now.

Unfortunately I've stopped working on this effort shortly after creating this repo & trying to get any minimal feedback/help from the McNeel discourse forum. I as well tried to buy the Rhino 7 to get back the samples that worked, but as you said that's not possible. TLDR: The Rhino 8 update killed pretty much all I had working 😅

I'm glad you found this repo useful, and I'm sorry I can't help you further. I hope you can find a way to get the samples working again. If you do, please let me know, I'd be happy to hear about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants