Results 1 to 36 of 36

Thread: plugins in vb.net

  1. #1

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729

    plugins in vb.net

    how can i dinamicly load plugins just like i could do in vb6..?

    i want a prog that has many plugins and it loads them at runtime...how do i do that?

    i tryed the old way and it seemed not to work

  2. #2
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    Well, I am in the process of working this out in .NET, but using C#. I will do my best to explain this. First off their are some things you should know about.

    1) Interfaces. These are very useful in a plug-in system. What they allow you to do is give plug-in writers a template of what functions they HAVE to use for your plug-in. In most cases plug-in systems need at least 1 base method that the main program can run, so you want that method to be known. When someone writes a plug-in dll, they can Implement the interface, this forces them to code whatever methods you define in the interface. Also in the base program you can detect what classes in a persons plug-in implements the correct interface and skip loading the dll if it does not.

    2) Reflection. This is the basis of the plug-in system. Reflection allows you to dynamically load a dll(plug-in) either by filename, partial class name, or full namespace/class name. Using the System.Reflection.Assembly and the File System stuff, you can loop through all files in directory, pass the filename into the .LoadFrom method of the Assembly class, get an array of classes in that assembly using .GetTypes(), (or load 1 specific class using assembly.GetType(classname)), and create an instance of the class. From there, there are all sorts of nifty little things you can do. you can even use the InvokeMember method of the Type class to run a method by passing in a string that is the Sub/function name. So in short look into Reflection, the Assembly class, and the Type class.

    3) Finally you would want to know how to use Collections to store instances of your loaded plug-ins to access whenever you need them.

    Here is my C# code the loads the dll dynamically. Now it may be in C#, but if you look carefully, you will notice that most of it it just like VB .NET. It has some comments to help explain what does what.

    This should at least help you get started. If you need some help understanding how to change something from C# to VB .NET, just ask and I will help you out with that, but most of it should be self explanatory. A couple perhaps not fully understandable is using = Imports in VB, [] brackets are array brackets, so in VB you use (), and variable declarations are like this in C# Type variablename; . That of course in VB would be Dim variablename As Type.

    Code:
    using System;
    using System.Reflection;
    
    namespace PluginLoad
    {
    	/// <summary>
    	/// Summary description for Class1.
    	/// </summary>
    	class VCommPlugInLoad
    	{
    		/// <summary>
    		/// The main entry point for the application.
    		/// </summary>
    		/// <args>Assembly_Name ObjectTypeName</args>
    		[STAThread]
    		static void Main(string[] args)
    		{
    			VCommPlugInLoad me = new VCommPlugInLoad();
    			me.LoadPlugIn(args[0]);
    		}
    		public void LoadPlugIn(string filename)
    		{
    			Type[] ObjType = null;
    			IPlugin plugin;
    			PlugInCollection plugList = new PlugInCollection();
    			
    			// load the dll. 
    			try
    			{
    				// load it
    				Assembly asm = null;
    				asm = Assembly.LoadFrom(filename);
    				if (asm != null)
    				{
    					// create an array of types
    					ObjType = asm.GetTypes();
    				}
    			}
                catch (Exception ex)
    			{
    				Console.WriteLine(ex.Message + "1");
    			}
    			try
    			{
    				// We need to find all classes that Implement the IPlugin interface
    				if (ObjType != null)
    				{
    					// lets loop through each type in our array of types in the loaded
    					// dll
    					foreach(Type pluginImplemented in ObjType)
    					{
    						
    						// If the plugin interface is bound to one of the types, then that type
    						// is a class that implements IPlugin.
    						if(pluginImplemented.GetInterface("IPlugin") != null)
    						{
    							//Console.WriteLine(pluginImplemented.ToString());
    							plugin = (IPlugin)Activator.CreateInstance(pluginImplemented);
    							//plugin.Settings();
    							pluginImplemented.InvokeMember("Settings", BindingFlags.Default | BindingFlags.InvokeMethod, null, plugin, new Object [0]);
    							// Initialize and add to collection
    							plugList.AddPlugin(plugin);	
    						}
    					}
    				}
    			}
                catch (Exception ex)
    			{
    				Console.WriteLine(ex.Message + "2");
    			}
    		}
    	}
    }
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  3. #3

    Thread Starter
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    yeah tks ill try doin it...and np i know the C# sintax

  4. #4
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    ahh coolness.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  5. #5
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    Thanks Cander saved me a whole heap of time searching around for how to load a dll at runtime.

    Here is the VB.NET translation of Cander's code for those that aren't familiar with the C# syntax:
    VB Code:
    1. Imports System
    2. Imports System.Reflection
    3.  
    4. 'Summary description for Class1.
    5. Class VCommPlugInLoad
    6.     'The main entry point for the application.
    7.     'Assembly_Name ObjectTypeName
    8.     Shared Sub Main(ByVal args() As String)
    9.         Dim m As New VCommPlugInLoad()
    10.         m.LoadPlugIn(args(0))
    11.     End Sub
    12.  
    13.     Public Sub LoadPlugIn(ByVal filename As String)
    14.         Dim ObjType() As Type
    15.         Dim plugin As IPlugin
    16.         Dim plugList As New PlugInCollection()
    17.  
    18.         'load the dll.
    19.         Try
    20.             'load it
    21.             Dim asm As [Assembly] = Nothing
    22.             asm = [Assembly].LoadFrom(filename)
    23.             If Not asm Is Nothing Then
    24.                 'create an array of types
    25.                 ObjType = asm.GetTypes()
    26.             End If
    27.         Catch ex As Exception
    28.             Console.WriteLine(ex.Message + "1")
    29.         End Try
    30.         Try
    31.             'We need to find all classes that Implement the IPlugin interface
    32.             If Not ObjType Is Nothing Then
    33.                 'lets loop through each type in our array of types in the loaded dll
    34.                 Dim pluginImplemented As Type
    35.                 For Each pluginImplemented In ObjType
    36.  
    37.                     'If the plugin interface is bound to one of the types, then that type
    38.                     'is a class that implements IPlugin.
    39.                     If Not pluginImplemented.GetInterface("IPlugin") Is Nothing Then
    40.                         'Console.WriteLine(pluginImplemented.ToString());
    41.                         plugin = CType(Activator.CreateInstance(pluginImplemented), IPlugin)
    42.                         'plugin.Settings();
    43.                         pluginImplemented.InvokeMember("Settings", BindingFlags.Default + BindingFlags.InvokeMethod, Nothing, plugin, New Object(0))
    44.                         'Initialize and add to collection
    45.                         plugList.AddPlugin(plugin)
    46.                     End If
    47.                 Next
    48.             End If
    49.         Catch ex As Exception
    50.             Console.WriteLine(ex.Message + "2")
    51.         End Try
    52.     End Sub
    53. End Class

    Feel free to make any necessary corrections, of course.

  6. #6
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    As a note ..you can also see how to run a subroutine by using its name as a string...which is a very popular VB6 question..and thus will be for .NET also.

    look at the InvokeMember method.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  7. #7
    Lively Member hbandarra's Avatar
    Join Date
    Aug 2002
    Location
    Lisbon, PT
    Posts
    66

    Thumbs up Very useful!

    I've started this subject in a new thread and Edneeis redirected me to here.

    Thanks Cander your useful explanation and Edneeis for your VB .Net translation!

  8. #8
    Lively Member hbandarra's Avatar
    Join Date
    Aug 2002
    Location
    Lisbon, PT
    Posts
    66

    Question

    Hi guys! Two simple questions:

    1st:
    Why do you call:
    Code:
    pluginImplemented.InvokeMember("Settings", BindingFlags.Default + BindingFlags.InvokeMethod, Nothing, plugin, New Object())
    instead of just:
    Code:
    plugin.Settings();
    as I am doing? Was it just an example of an alternative way?

    2nd:
    What is the normal process in deploying an Interface for 3rd parties to develop plugins?
    What kind of information is usually given?

    Thx!

  9. #9
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    1) I was experimenting with calling a sub routine by using its name as a string. Both ways work.

    2) The interface should just be a dll or just a class with the names of functions/subs/properties that the plugin writer must Implement in their plugin. That way your main application will always know what the actual routine names are.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  10. #10
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    Just found your code, very nice & exactly what I want to do. Just "two" questions. What are IPlugin & PlugInCollection?
    If you can dream it, you can do it - Moo Power!

  11. #11
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    He used a standard Interface (IPlugin) to define the structure of a plugin. Each plugin must implement that interface to be a plugin. You could also make a PluginBase class and have all plugins inherit from it if you want. The PluginCollection is a collectio nof the objects that implement IPlugin (a.k.a A collection of Plugins).

  12. #12
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    ahh, ok, that makes sence. Thank-you!
    If you can dream it, you can do it - Moo Power!

  13. #13
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    Going further on the IPlugin.

    Basically it gives me the ability to provide the 'rules' a third party developer must follow in order to make a plugin for the app and it lets me verify that they indeed did follow those rules before running the plugin.

    When i say rules, I mean what properties and methods that a developer MUST have as a minimum so that the main app knows what to call.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  14. #14
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    That makes sence, as you don't want them not specifying methods that you call, and thus crashing the program.

    I am having trouble casting the Activator.CreateInstance() to the plugin variable though

    If I specify plugin as an object, at use InvokeMember() to call methods, it works fine, but I'd rather cast it as an IPlugin, so it all just works better.

    Any ideas?
    If you can dream it, you can do it - Moo Power!

  15. #15
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    Hmm. what kind of problem?
    What kind of changes did you do to the orginal code if any, and what were they?
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  16. #16
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    the original code is exactly the same, with the exception that I took out the plugin collection (to simplify things). I also renamed a few variables, and placed a few more visual information in the console:

    PHP Code:
    using System;
    using System.Reflection;

    namespace 
    PluginLoad {
      
      public interface 
    tfxPlugin {
        
    string Author();
        
    string Name();
        
    string Version();
        
    string Info();
        
    bool Initialize();
        
    bool Shutdown();
        
      }

      class 
    LoadPlugin {

        static 
    void Main(string[] args)  {
          
    Type[] ObjType null;
          
    tfxPlugin plugin;
          
    string filename "../dll1/dll1.dll";
          
          
    // load the dll. 
          
    try  {
            
    // load it
            
    Assembly asm null;
            
    asm Assembly.LoadFrom(filename);
            if (
    asm != null) {
              
    // create an array of types
              
    ObjType asm.GetTypes();
              
    Console.WriteLine("Interogating: " filename);
            }
            
          } catch (
    Exception ex) {
            
    Console.WriteLine(ex.Message "1");
          }
          
          try  {
            
    // We need to find all classes that Implement the IPlugin interface
            
    if (ObjType != null) {
              
    // lets loop through each type in our array of types in the loaded
              // dll
              
    foreach(Type pluginImplemented in ObjType) {
                
                
    Console.WriteLine("Found: " pluginImplemented.ToString());

                
    // If the plugin interface is bound to one of the types, then that type
                // is a class that implements IPlugin.
                
    if(pluginImplemented.GetInterface("tfxPlugin") != null) {
                  
    Console.WriteLine("Loading: " pluginImplemented.GetInterface("tfxPlugin"));
                  
                  
    plugin = (tfxPlugin)Activator.CreateInstance(pluginImplemented);
                  
                  
    // put Initialize code here
                  
    Console.WriteLine("Loaded: " plugin.Name());
                  
                }
              }
            }
          }
          catch (
    Exception ex) {
            
    Console.WriteLine(ex.Message "2");
            
          }
        }
      }

    My DLL is like so:

    PHP Code:
    // project created on 06/05/2003 at 16:26
    using System;

    public interface 
    tfxPlugin {
      
    string Author();
      
    string Name();
      
    string Version();
      
    string Info();
      
    bool Initialize();
      
    bool Shutdown();
      
    }

    public class 
    DLL1tfxPlugin
    {
      public 
    string Author() {
        return 
    "Vitani";
      }
      
      public 
    string Name() {
        return 
    "Test Plugin #1";
      }
      
      public 
    string Version() {
        return 
    "1.0";
      }
      
      public 
    string Info() {
        return 
    "This is to test the plugin code";
      }
      
      public 
    bool Initialize() {
        return 
    true;
      }
      
      public 
    bool Shutdown() {
        return 
    true;
      }


    If you can dream it, you can do it - Moo Power!

  17. #17
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    But what is the problem?
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  18. #18
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    on the line

    plugin = (tfxPlugin)Activator.CreateInstance(pluginImplemented);

    I get the error "Specified cast is not valid."
    If you can dream it, you can do it - Moo Power!

  19. #19
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    also, on a related matter, can the plugins call functions in the main application? So things like get_word() or word_count() can be built into the exe and don't have to have to be in each dll. I'll be doing a lot of string minipulation, and i've written a lot of string parsing functions that I'd like to have in the main exe, and available in the plugins
    If you can dream it, you can do it - Moo Power!

  20. #20
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    Im working on figuring out your problem.

    About yopur other question. Put those functions into their own seperate dll. Then you can call it from your main app and the plugins.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  21. #21
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    ok here we go.

    First get rid of the Interface definition in the main executable.

    Then, put your Interface definition in its OWN dll.

    Remove the interface definition from the plugin.

    Then add references to the interface dll in your plugin and exe.

    Should work fine.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  22. #22
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    ok, I've done all that, but now I get this error:

    Unhandled Exception: System.IO.FileNotFoundException: File or assembly name Interface, or one of its dependencies, was not found.
    File name: "Interface" at PluginLoad.LoadPlugin.Main(String[] args)

    I did exactly what you said. Word for word.

    This error occurs before any code is exectuted
    If you can dream it, you can do it - Moo Power!

  23. #23
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    You need to re paste all your code again, because you did something wrong.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  24. #24
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    Main executable:

    References tfxInterface.dll

    PHP Code:
    using System;
    using System.Reflection;

    namespace 
    PluginLoad {
      
      class 
    LoadPlugin {

        static 
    void Main(string[] args)  {
          
    Type[] ObjType null;
          
    tfxInterface.tfxPlugin plugin;
          
    string filename "../dll1/dll1.dll";
          
          
    // load the dll. 
          
    try  {
            
    // load it
            
    Assembly asm null;
            
    asm Assembly.LoadFrom(filename);
            if (
    asm != null) {
              
    // create an array of types
              
    ObjType asm.GetTypes();
              
    Console.WriteLine("Interogating: " filename);
            }
            
          } catch (
    Exception ex) {
            
    Console.WriteLine(ex.Message "1");
          }
          
          try  {
            
    // We need to find all classes that Implement the IPlugin interface
            
    if (ObjType != null) {
              
    // lets loop through each type in our array of types in the loaded
              // dll
              
    foreach(Type pluginImplemented in ObjType) {
                
                
    Console.WriteLine("Found: " pluginImplemented.ToString());

                
    // If the plugin interface is bound to one of the types, then that type
                // is a class that implements IPlugin.
                
    if(pluginImplemented.GetInterface("tfxPlugin") != null) {
                  
    Console.WriteLine("Loading: " pluginImplemented.GetInterface("tfxPlugin"));
                  
                  
    plugin = (tfxInterface.tfxPlugin)Activator.CreateInstance(pluginImplemented);
                  
                  
    // Initialize
                  //Console.WriteLine("Loaded '{0}'", pluginImplemented.InvokeMember("Name", BindingFlags.Default | BindingFlags.InvokeMethod, null, plugin, new Object [0]));
                  
    Console.WriteLine("Loaded: " plugin.Name());
                  
                }
              }
            }
          }
          catch (
    Exception ex) {
            
    Console.WriteLine(ex.Message "2");
            
          }
        }
      }

    Plugin DLL (dll1.dll):

    References tfxInterface.dll

    PHP Code:
    // project created on 06/05/2003 at 16:26
    using System;

    public class 
    DLL1tfxInterface.tfxPlugin
    {
      public 
    string Author() {
        return 
    "Vitani";
      }
      
      public 
    string Name() {
        return 
    "Test Plugin #1";
      }
      
      public 
    string Version() {
        return 
    "1.0";
      }
      
      public 
    string Info() {
        return 
    "This is to test the plugin code";
      }
      
      public 
    bool Initialize() {
        return 
    true;
      }
      
      public 
    bool Shutdown() {
        return 
    true;
      }


    Interface DLL (tfxInterface.dll):

    PHP Code:
    public class tfxInterface
    {
      public interface 
    tfxPlugin {
        
    string Author();
        
    string Name();
        
    string Version();
        
    string Info();
        
    bool Initialize();
        
    bool Shutdown();
      }

    All fun & games is this
    If you can dream it, you can do it - Moo Power!

  25. #25
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    you dont put interfaces IN a class. Change tfxInterface to a namespace
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  26. #26
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    oops!

    PHP Code:
    namespace tfxInterface
    {
      public interface 
    tfxPlugin {
        
    string Author();
        
    string Name();
        
    string Version();
        
    string Info();
        
    bool Initialize();
        
    bool Shutdown();
      }

    still crashes, same error
    If you can dream it, you can do it - Moo Power!

  27. #27
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    you didnt move the Interface dll after setting references did you?
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  28. #28
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    nope, and I rebuilt all 3 parts when I updatedthe interface
    If you can dream it, you can do it - Moo Power!

  29. #29
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    Think you could zip up your project files and attach them to a reply here? Something is not kosher as the above works perfectlly for me.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  30. #30
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    sorry I took so long to reply, I installed .NET 1.1, rebooted & reinstalled #Dev. Still doesn't work

    So here it is...
    Attached Files Attached Files
    If you can dream it, you can do it - Moo Power!

  31. #31
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    I think you got something bound up and nutty going on with SharpDevelop. I would suggest creating a new set of projects, and copy and paste the code to the new projects, compile the interface dll, then add it as a reference for the pluigin and exe and try it. Whatever it is , I think it is a quirk with Sharp Deveop
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  32. #32
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    ah ha! I put the interface dll in the same folder as the exe, and it worked. Rah, thanks for ALL your help Cander, and for you code.

    Pure genius.
    If you can dream it, you can do it - Moo Power!

  33. #33
    Banished Cander's Avatar
    Join Date
    Dec 2000
    Location
    Why do you care?
    Posts
    6,913
    ahh ok. Your welcome.
    Stack Overflow
    See the features of Visual Studio 2010 and C# 4.0: The 10-4 show on Channel9

  34. #34
    Frenzied Member Mike Hildner's Avatar
    Join Date
    Jul 2002
    Location
    Des Moines, NM
    Posts
    1,690
    Has anyone made a plugin app for a mobile device (Compact Framework)? I about to give it a try, just wondering if there were any caveats.

    Thanks,
    Mike

  35. #35
    Addicted Member Vitani's Avatar
    Join Date
    Jul 2001
    Location
    England
    Posts
    134
    I've not tried it on the CF, but you may need to download extra bits to complament the framework to get it working.

    Check out the assemblies at OpenNetCF.org - they add a lot of the full framework's abilities to the compact framework

    If you get it working, I'd love to hear about it!
    If you can dream it, you can do it - Moo Power!

  36. #36
    Frenzied Member Mike Hildner's Avatar
    Join Date
    Jul 2002
    Location
    Des Moines, NM
    Posts
    1,690
    Searching around, there's an excellent article, courtesy of MSDN.
    http://msdn.microsoft.com/msdnmag/is...s/default.aspx

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width