New way to load a C# .net plugin

Hi guys, I put this post to share a new way to load a C# plugin.
Avoiding restart Rhino every time that recompile a plugin.
Using this technique the code compile and try time is more fast.

Managed Extensibility Framework (MEF) Plugin for Rhinoceros RhinoCommon

Hope will be usefull.
Greetings…

11 Likes

I’ve tested this method today, and can report that it works. Thank you for making this technique available, this will certainly cut down our time spent in the compile-run-debug cycle. If only I knew about this four years ago :wink:

Even more faster:

If sometime must to change between many plugin, and write the full path dll name is a lack of time:
Store the default dll names in a txt file, doing this
not need to recompile the RhinoPluginLoader to change the default dll name,

In the LoadPlugin.cs, RunCommand change for this:

// Was a plugin named entered?
string plugin_name = gs.StringResult().Trim();
if (string.IsNullOrEmpty(plugin_name))
{
plugin_name = LoadDefaultDll();
}

Configuration txt file with the dll names:

D:\the path\plugin.dll
D:\the path\anotherplugin.dll
D:\the path\anothermoreplugin.dll

private string LoadDefaultDll() 
{
    string filename = @"D:\Visual Studio Projects\RhinoPluginLoader\defaultdll.txt";

    if (!System.IO.File.Exists(filename))
    {
        Rhino.RhinoApp.WriteLine("defaultdll file not exist !!!");
        return "";
    }            
   
    StreamReader sr = new StreamReader(filename);
    string defaultdll="";
    if (!sr.EndOfStream)
    {
        defaultdll = sr.ReadLine();//Load firt line
    }       
    sr.Close();
    return defaultdll;          
}

In rhino with two [ENTER] load the default dll.
Then you can run the first dll, or add more code to ask to user to enter a line number:

1 load first plugin
2 load second plugin
etc

Greetings

This actually works! I didn’t know there were more options.

I use a program called SharpDevelop, a C# IDE, and it has the option of compiling the code without running it. I use that to save time, that’s also another option.

I am happy to also confirm this seems to be working…the restart/reload cycle was a deterrent for me to use c#.

I am fairly new to c# and was a little confused on the imports. I would recommend making the ‘RhinoPluginContract’ class first so you can reference it in the ‘RhinoPluginMakeLine’ and the ‘PluginLoader’, and you don’t get errors on the ‘IPlugin’ references. If you follow the flow in the article then you make the contract last.

I am using visual studio 2015 and the target for the new class library template was .net 4.5.2. I guess the Rhino template is set to 4.5.0, so I got a warning when compiling the ‘PluginLoader’. I just changed the target to 4.5.2 in project properties and it seems to be OK.

Thanks for sharing this!

merci @marceloarguello700

Hi all, trying to implement this. How do I go about using this technique in a plugin I’ve already worked on which has a few commands? I got both the RhinoPluginContract and PluginLoader to work but am wondering now how to make these work with a plugin I’ve already started on. Do you put this part:

[Export(typeof(IPlugin))]

public class CodeEjecutor : IPlugin
{

into the plugin file or in each command file of the plugin?

Hi,

Thanks for the MEF plugin explanation it works for me too.

What is the workflow when you want to add a new command?
For instance if I want to add LoadPlugin2 command that does something else. Do I need to add new IPlugin2 class and CodeExecutor2? If yes will it ask restart rhino for the new command?

Hello,

My workflow with SharpDevelop regarding the addition of a new command is very simple. In my PluginCommand.cs file, I duplicate the existing class and rename all instances of the old name, and it will work as intended. For instance, here is an example of my command file:

using System;
using System.Collections.Generic;
using Rhino;
using Rhino.Commands;
using Rhino.Geometry;
using Rhino.Input;
using Rhino.Input.Custom;

namespace PlotEquation
{
    public class EquationCurveCommand : Command
    {
        public EquationCurveCommand()
        {
            // Rhino only creates one instance of each command class defined in a
            // plug-in, so it is safe to store a refence in a static property.
            Instance = this;
        }

        ///<summary>The only instance of this command.</summary>
        public static EquationCurveCommand Instance
        {
            get; private set;
        }

        ///<returns>The command name as it appears on the Rhino command line.</returns>
        public override string EnglishName
        {
            get { return "EquationCurve"; }
        }

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            // TODO: start here modifying the behaviour of your command.
            // ---
            RhinoApp.WriteLine("{0} will plot a graph.\n", EnglishName);
            // ---

            return Result.Success;
        }
    }

    public class EquationSurfaceCommand : Command
    {
        public EquationSurfaceCommand()
        {
            // Rhino only creates one instance of each command class defined in a
            // plug-in, so it is safe to store a refence in a static property.
            Instance = this;
        }

        ///<summary>The only instance of this command.</summary>
        public static EquationSurfaceCommand Instance
        {
            get; private set;
        }

        ///<returns>The command name as it appears on the Rhino command line.</returns>
        public override string EnglishName
        {
            get { return "EquationSurface"; }
        }

        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            // TODO: start here modifying the behaviour of your command.
            // ---
            RhinoApp.WriteLine("{0} will plot a graph.\n", EnglishName);
            // ---

            return Result.Success;
        }
    }
}

My apologies on the late reply, I have not been on this forum in quite some time.

Could you share will full visual studio project to see the structure?

Here is the basic structure of the plugin I worked on when I responded here in 2016: Basic Structure v5.zip. Let me know if you have any questions or if it doesn’t run as intended.

1 Like

Thanks

@Petras_Vestartas did you see how to do it this way?

Will this method work for GH plugin?

Yes, we use it all the time.

For those who want a similar approach for Grasshopper development, I’ve set up a starter kit and explanation here: