Click here to Skip to main content
15,923,083 members

Welcome to the Lounge

   

For discussing anything related to a software developer's life but is not for programming questions. Got a programming question?

The Lounge is rated Safe For Work. If you're about to post something inappropriate for a shared office environment, then don't post it. No ads, no abuse, and no programming questions. Trolling, (political, climate, religious or whatever) will result in your account being removed.

 
GeneralRe: I need to use MAF Pin
Dave Kreskowiak26-Jul-16 9:36
mveDave Kreskowiak26-Jul-16 9:36 
GeneralRe: I need to use MAF Pin
#realJSOP26-Jul-16 11:03
professional#realJSOP26-Jul-16 11:03 
GeneralRe: I need to use MAF Pin
TheGreatAndPowerfulOz26-Jul-16 12:02
TheGreatAndPowerfulOz26-Jul-16 12:02 
GeneralRe: I need to use MAF Pin
Brisingr Aerowing26-Jul-16 14:08
professionalBrisingr Aerowing26-Jul-16 14:08 
GeneralRe: I need to use MAF Pin
#realJSOP27-Jul-16 2:36
professional#realJSOP27-Jul-16 2:36 
GeneralRe: I need to use MAF Pin
Dave Kreskowiak27-Jul-16 2:59
mveDave Kreskowiak27-Jul-16 2:59 
GeneralRe: I need to use MAF Pin
#realJSOP27-Jul-16 3:10
professional#realJSOP27-Jul-16 3:10 
GeneralRe: I need to use MAF Pin
Dave Kreskowiak27-Jul-16 3:26
mveDave Kreskowiak27-Jul-16 3:26 
The source of SourceForge has an example application in it, so that helped.

The only other example I know of is a GitHub (because of course it is), here[^]

How about this to get you started:

First, the pluggable application.

1. Open your pluggable application project in Visual Studio.
2. Add a reference to the SimplePlugins.dll from your project.
3. Add using/imports directives where you would like to initialize and use the plugin loader provided by the library like so,

C#
using SimplePlugins;
using SimplePlugins.Exceptions;



4. Initialize the PluginLoader object like so,

C#
this.PluginLoader = new PluginLoader();



5. You can specify additional paths where plugin dependencies will be located like so,

C#
this.PluginLoader.AssemblyResolutionPaths.Add(Application.StartupPath);



6. You can make the plugin loader use the .Net framework’s shadow copy option when loading assemblies like so, (You can further customize the cache path, etc by handling the PluginLoader.PluginLoading event)

C#
this.PluginLoader.ShadowCopyEnabled = true;



7. You can then hook up to the several events which enable the pluggable application to manage plugin behavior like so,

C#
//This event fires when PluginLoaderBase.Probe is complete.
this.PluginLoader.ProbeComplete += new PluginLoaderBase.ProbeCompleteEventHandler(PluginLoader_ProbeComplete);

//This event fires before PluginLoaderBase.Load creates the AppDomain object which will be used to load the plugin from the plugin assembly.
this.PluginLoader.PluginLoading += new PluginLoaderBase.PluginLoadingEventHandler(PluginLoader_PluginLoading);

//This event fires when PluginLoaderBase.Load completes loading the plugin from the plugin assembly.
this.PluginLoader.PluginLoaded += new PluginLoaderBase.PluginLoadedEventHandler(PluginLoader_PluginLoaded);

//This event fires when PluginLoaderBase.Load completes the execution and unloading of the loaded plugin
this.PluginLoader.PluginUnloaded += new PluginLoaderBase.PluginUnloadedEventHandler(PluginLoader_PluginUnloaded);



8. You can probe available plugins from a location in the hard disk as follows, The PluginLoader.Probe method scans the specified directory and subdirectories for valid plugin assemblies and returns a list.

C#
PluginInfoList pluginInfoList = this.PluginLoader.Probe("C:\plugins", SearchOption.AllDirectories);
for (int i = 0; i < pluginInfoList.Count; i++)
    lbPlugins.Items.Add(pluginInfoList[i]);



9. Use the PluginLoader.Load method to execute any of the plugins returned by the PluginLoader.Probe method above. Parameters can also be passed to the plugin using the PluginParameters class. Any unhandled exceptions which may occur during the loading process is wrapped by the serializable PluginException class and rethrown to make sure no AppDomain leakages occur. Hence the try-catch block.

C#
//Get the PluginInfo object selected by the user for execution.
PluginInfo template = (PluginInfo)lbPlugins.SelectedItem;
try
{
    //Create a PluginParameters object and add any parameters to be passed to the plugin
    PluginParameters args = new PluginParameters();
    args.Add("Param1", "The quick brown fox jumped over the lazy dog");
    args.Add("Param2", 100);
    args.Add("Param3", 7.321);

    //Tell the plugin loader to load and execute the plugin
    this.PluginLoader.Load(template.FileName, args);
}
catch (PluginException ex)
{
    Console.WriteException(ex);
}



10. You may use the PluginLoader.NotifyUnload or PluginLoader.NotifyUnloadAll methods to notify a plugin that it needs to be unloaded.
11. You can use the PluginLoader.PluginUnloaded event to check whether plugins executed successfully and their return values as follows.

C#
void PluginLoader_PluginUnloaded(object sender, PluginLoaderBase.PluginUnloadedEventArgs e)
{
    //Check if the plugin was unloaded due to an exception
    //The PluginException class wraps any unhandled exception in a serializable wrapper.
    //The PluginException class also exposes all InnerExceptions of the actual exception through PluginException.InnerException as well
    //This makes sure that unhandled non-serializable exceptions do not cause unexpected AppDomain leaks in the main application.
    if (e.Results.UnhandledException != null)
        Console.WriteException("The plugin '" + e.Info.ToString() + "' was unloaded due to unhandled exception: " + e.Results.UnhandledException.ToString());
    else if (e.Results.ExecutionDenied)
    {
        //Plugins can be denied execution by the PluginLoader object according to the specified value in PluginBase.ExecutionMode property.
        //This checks which execution modes prevented the plugin from being executed.
        if (e.Info.ExecutionMode == PluginBase.ExecutionModes.AsynchronousExclusive || e.Info.ExecutionMode == PluginBase.ExecutionModes.SynchronousExclusive)
            Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded since it is intended to be executed exclusively. Please make sure no other plugin is executing and try again.");
        else if (e.Info.ExecutionMode == PluginBase.ExecutionModes.AsynchronousSingleton || e.Info.ExecutionMode == PluginBase.ExecutionModes.SynchronousSingleton)
            Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded since only one instance of it is intended to be executed at a time. Please make sure no other instance of the same plugin is executing and try again.");
        else
            Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded.");
    }
    else
    {
        //Each plugin may return results in the form of a PluginParameters object exposed by the PluginLoaderBase.PluginUnloadedEventArgs.Results property
        //This object can be checked for values returned by the plugin like so,
        if (e.Results.Contains("ReturnValue"))
            Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded successfully with the return value: " + Convert.ToString(e.Results.Get("ReturnValue")));
        else
            Console.WriteInfo("The plugin '" + e.Info.ToString() + "' was unloaded successfully");
    }
}



That’s it! You have got yourself a pluggable application. Now you can write a plugin by following the steps below.

1. Open or create a project for the plugin in Visual Studio. This can be an executable type project or a class library project.
2. Add a reference to the SimplePlugins.dll.
3. Add a class under any name which will represent the plugin. Derive this class from the PluginBase abstract class provided by the Simple Plugins library and override its methods appropriately. Place your main processing code inside the Main method. The Main method is called by the PluginLoader.Load method after the plugin is successfully loaded.

C#
using SimplePlugins;
using SimplePlugins.Exceptions;

namespace SamplePluggableApp.SamplePlugin
{
    public class Plugin : PluginBase
    {
        public Plugin()
            : base()
        {
        }

        internal string Param1 { get; private set; }
        internal int Param2 { get; private set; }
        internal double Param3 { get; private set; }

        public override string FriendlyName
        {
            //The friendly name of the plugin. This will be used by default in PluginInfo.ToString()
            get { return "Sample Plugin"; }
        }

        public override ExecutionModes ExecutionMode
        {
            get { return ExecutionModes.AsynchronousMultiInstance; } //Tells Loader to allow loading of multiple instances asynchronously in seperate threads
            //ExecutionModes.AsynchronousExclusive - PluginLoaderBase object will execute plugin in a seperate thread only if no other plugins are running
            //ExecutionModes.AsynchronousMultiInstance - PluginLoaderBase object will execute plugin in a seperate thread and will allow multiple instances of the plugin to be executed simultaneously
            //ExecutionModes.AsynchronousSingleton - PluginLoaderBase object will execute plugin in a seperate thread and will allow only one instance of the plugin to be running at a time
            //ExecutionModes.SynchronousExclusive - PluginLoaderBase object will execute plugin in the same thread as the pluggable app only if no other plugins are running
            //ExecutionModes.SynchronousMultiInstance - PluginLoaderBase object will execute plugin in the same thread as the pluggable app and will allow multiple instances of the plugin to be executed simultaneously
            //ExecutionModes.SynchronousSingleton - PluginLoaderBase object will execute plugin in the same thread as the pluggable app and will allow only one instance of the plugin to be running at a time
        }

        public override PluginParameters Main(PluginParameters args)
        {
            //Assigns parameters passed from the pluggable app to public members
            this.Param1 = (string)args.Get("Param1");
            this.Param2 = (int)args.Get("Param2");
            this.Param3 = (double)args.Get("Param3");

            MainView pluginForm = new MainView();
            pluginForm.Show(); //show the main plugin window

            Application.Run(pluginForm); //This starts a new message loop for the plugin window. pluginForm.ShowDialog() may also be used instead.
            //Specifying ExecutionMode as Synchronous* and calling pluginForm.ShowDialog() will show the form in dialog mode and block the Pluggable App.

            args.Add("ReturnValue", "Success"); // Demonstrates how serializeable/primitive types can be passed back to the pluggable app
            //returned values will be available in the pluggable app via PluginLoaderBase.PluginUnloaded event

            return args;
        }

        public override void OnUnloadNotification()
        {
            //This method is called by PluginLoaderBase.NotifyUnload or PluginLoaderBase.NotifyUnloadAll to notify the plugin that it is about to be unloaded.
            //You can write code which will stop plugin process and do cleanup here
            Application.Exit();
        }
    }
}



That’s all there is to it. Place the output of your plugin project in the plugins folder path and let Simple Plugins do everything else for you. If the functionality provided by the standard PluginLoader and PluginBase classes are not enough, you can extend those classes to meet your own needs. You may refer the code on how the default PluginLoader class is implemented to get an idea about writing a custom loader.
A guide to posting questions on CodeProject

Click this: Asking questions is a skill.
Seriously, do it.

Dave Kreskowiak

GeneralRe: I need to use MAF Pin
#realJSOP27-Jul-16 4:15
professional#realJSOP27-Jul-16 4:15 
GeneralRe: I need to use MAF Pin
#realJSOP27-Jul-16 5:43
professional#realJSOP27-Jul-16 5:43 
GeneralRe: I need to use MAF Pin
Dave Kreskowiak27-Jul-16 6:01
mveDave Kreskowiak27-Jul-16 6:01 
GeneralRe: I need to use MAF Pin
Slacker00726-Jul-16 10:40
professionalSlacker00726-Jul-16 10:40 
GeneralRe: I need to use MAF Pin
Slacker00726-Jul-16 10:36
professionalSlacker00726-Jul-16 10:36 
GeneralRe: I need to use MAF Pin
dandy7226-Jul-16 10:27
dandy7226-Jul-16 10:27 
GeneralRe: I need to use MAF Pin
Sander Rossel26-Jul-16 21:26
professionalSander Rossel26-Jul-16 21:26 
GeneralRe: I need to use MAF Pin
Marco Bertschi27-Jul-16 0:19
protectorMarco Bertschi27-Jul-16 0:19 
GeneralThought of the day Pin
OriginalGriff26-Jul-16 4:57
mveOriginalGriff26-Jul-16 4:57 
GeneralRe: Thought of the day Pin
Mark_Wallace26-Jul-16 5:25
Mark_Wallace26-Jul-16 5:25 
GeneralRe: Thought of the day Pin
Wastedtalent26-Jul-16 5:46
professionalWastedtalent26-Jul-16 5:46 
GeneralRe: Thought of the day Pin
Marc Clifton26-Jul-16 5:47
mvaMarc Clifton26-Jul-16 5:47 
GeneralRe: Thought of the day Pin
OriginalGriff26-Jul-16 5:56
mveOriginalGriff26-Jul-16 5:56 
GeneralRe: Thought of the day Pin
W Balboos, GHB26-Jul-16 6:07
W Balboos, GHB26-Jul-16 6:07 
GeneralRe: Thought of the day Pin
ricmil4226-Jul-16 6:26
ricmil4226-Jul-16 6:26 
GeneralRe: Thought of the day Pin
Vincent Maverick Durano26-Jul-16 6:36
professionalVincent Maverick Durano26-Jul-16 6:36 
GeneralRe: Thought of the day Pin
Corporal Agarn26-Jul-16 6:48
professionalCorporal Agarn26-Jul-16 6:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.