1. مهمان گرامی، جهت ارسال پست، دانلود و سایر امکانات ویژه کاربران عضو، ثبت نام کنید.
    بستن اطلاعیه

آموزش ساخت plug in با استفاده از Vb.net and C#‎.net

شروع موضوع توسط minaaa ‏29/1/11 در انجمن .Net

  1. کاربر پیشرفته

    تاریخ عضویت:
    ‏9/12/10
    ارسال ها:
    19,773
    تشکر شده:
    6,457
    امتیاز دستاورد:
    113
    پلاگین چیست؟

    پلاگین برنامه است که با اضافه شدن به برنامه ای قابلیتهایی به ان برنامه اضافه می کند.

    حتما شما با flash player اشنا هستید. برنامه ای که با نصب آن مرورگر شما
    قابلیت پخش انیمیشن های فلش را پیدا می کند. این برنامه یک پلاگین برای
    نرم مرورگر شماست.

    پلاگین در .net framework

    برای نوشتن برنامه ای در دات نت که قابلیت پذیرش پلاگین باشد به سه لایه احتیاج دارد

    1.لایه رابط

    2.لایه برنامه

    3.لایه پلاگین

    حالا بریم سروقت پروژه و هریک از سه لایه بالا را با تفصیل توضیح دهیم.

    پروژه

    یک برنامه ساده می خواهیم ایجاد کنیم که قابلیت پذیرش پلاگین را داشته
    باشد. این برنامه حاوی یک فرم است که روی ان دو عدد textbox است و می
    خواهیم پلاگین بنویسیم که به کنترلهای textbox روی فرم اصلی دسترسی پیدا
    کند و حاصلضرب دو عدد داخل textbox را بدست آورد و منویی هم به من فرم
    اصلی اضافه کند.

    حالا یک solution در vs ایجاد کنید و یک پروژه جدید از نوع class library
    به نام IPlugin به آن اضافه کنید تا اولین لایه برنامه را ایجاد کنیم.

    لایه رابط

    حالا یک code file به پروژه اضافه کرده و با توجه به زبان یکی از کدهایه زیر را در ان قرار دهید.

    با زبان وی بی





    کد:
    Public Interface IPlugin



    Property Name() As String



    Sub About()

    Sub DisplayPlugForm()

    Sub GetMessage(ByVal msg As String)



    Event SendMessage(ByVal msg As String, ByVal IPlugin As IPlugin)

    Property menu() As Windows.Forms.ToolStripItemCollection



    End Interface</pre>


    با زبان سی شارپ

    کد:

    کد:
    namespace SDK {

    public delegate void EventHandler(string msg, IPlugin IPlugin);

    public interface IPlugin

    {

    string name();

    void About();

    void DisplayPlugForm();

    void GetMessage(string msg);

    event EventHandler SendMessage;

    System.Windows.Forms.ToolStripItemCollection menu();



    }

    }</pre>


    خوب interface بالا متدها و رویداها و خاصیتهایی که باید در هر پلاگین باشد را توصیف می کند.

    خاصیت name این خاصیت حاوی نام پلاگین است.

    خاصیت menu این خاصیت حاوی منوهایی است که می خواهیم به برنامه اصلی اضافه شود.

    متد about این متد فرم توضیحات پلاگین را نمایش خواهد داد.

    متد DisplayPlugForm فرم اصلی پلاگین را نمایش می دهد.

    متد GetMessage این متد برای فرستادن پیغام از برنامه اصلی به پلاگین بکار می رود.

    رویداد SendMessage این رویداد وقتی اجرا می شود که بخواهیم پیغامی را از پلاگین به برنامه اصلی بفرستیم .

    خوب لایه اول تمام شد.


    لایه برنامه

    ابتدا یک پروژه جدید از نوع application به نام program به solution خود
    اضافه کنید و پروژه قبلی را به فهرست رفرنس های این پروژه اضافه کنید.

    این قسمت برنامه شامل دو کلاس مهم است.

    اولین کلاس IPlugin_Collection این کلاس همانطور که از نامش پیداست یک
    مجموعه است که ما تمام پلاگین هایه خودمان را در ان نگه می داریم کد این
    کلاس

    وی بی

    کد:

    کد:
    Imports sdk



    Public Class IPlugin_Collection

    Inherits CollectionBase



    Public Property item(ByVal iIndex As Integer) As IPlugin

    Get

    Return (InnerList.Item(iIndex))

    End Get

    Set(ByVal Value As IPlugin)

    InnerList.Item(iIndex) = Value

    End Set

    End Property



    Public Function add(ByVal iPluginObj As IPlugin) As Integer

    Return InnerList.Add(iPluginObj)



    End Function



    Public Function contains(ByVal iPluginObj As IPlugin) As Boolean

    Return (InnerList.Contains(iPluginObj))

    End Function



    Public Function indexOf(ByVal iPluginObj As IPlugin) As Integer

    Return (InnerList.IndexOf(iPluginObj))

    End Function



    Public Sub remove(ByVal iPluginObj As IPlugin)

    Call InnerList.Remove(iPluginObj)

    End Sub







    End Class</pre>


    با سی شارپ

    کد:

    کد:
    using System;

    using System.Collections.Generic;

    using System.Text;

    using SDK;



    namespace program

    {

    public class IPlugin_Collection : System.Collections.CollectionBase

    {

    public IPlugin this[int index]

    {

    get

    {

    return (IPlugin )this.InnerList[index];

    }

    set

    {

    this.InnerList[index] = value;

    }

    }

    public int add(IPlugin iPluginObj)

    {

    return this.InnerList.Add(iPluginObj);



    }

    public bool contains(IPlugin iPluginObj)

    {

    return this.InnerList.Contains(iPluginObj);

    }

    public int indexOf(IPlugin iPluginObj)

    {

    return this.InnerList.IndexOf(iPluginObj);

    }

    public void remove(IPlugin iPluginObj)

    {

    this.InnerList.Remove(iPluginObj);

    }

    }

    }</pre>


    فکر نکنم نیازی به توضیح باشد.

    کلاس بعدی کلاس plugin_manager است در این کلاس ما پلاگین ها را لود می کنیم.

    ما برای لود پلاگین ها علاوه بر داشتن فایل dll انها باید نام کلاس اصلی
    این پلاگین ها که براساس انترفیس پروژه اول ما شکل گرفته اند را باید
    داشته باشیم.من در این برنامه اطلاعات پلاگین ها را در ریجیستری ذخیره
    کردم.که بعدا در این مورد بیشتر توضیح میدهیم حالا کد کلاس

    وی بی

    کد:

    کد:
    Imports SDK

    Public Class plugin_manager

    Public cPicPlugins As New IPlugin_Collection()

    Public Event reciveMessage(ByVal msg As String, ByVal IPlugin As IPlugin)



    Private Sub recive(ByVal msg As String, ByVal IPlugin As IPlugin)

    RaiseEvent reciveMessage(msg, IPlugin)

    End Sub





    Public Sub load_plugin()

    Dim r, r1, r2 As Microsoft.Win32.RegistryKey

    Dim s(), s1, pStrPath, pStrType As String

    r = Microsoft.Win32.Registry.LocalMachine

    r1 = r.OpenSubKey("SOFTWARE\my program\plug in", False)

    s = r1.GetSubKeyNames

    For Each s1 In s

    Try

    r2 = r1.OpenSubKey(s1)

    pStrPath = r2.GetValue("path")

    pStrType = r2.GetValue("type")

    Catch ex As Exception

    End Try

    Try

    Dim pObhHandle As Runtime.Remoting.ObjectHandle = Activator.CreateInstanceFrom(pStrPath, pStrType)

    Dim pIpnPlugin As SDK.IPlugin = CType(pObhHandle.Unwrap, SDK.IPlugin)

    Call cPicPlugins.add(pIpnPlugin)

    AddHandler pIpnPlugin.SendMessage, AddressOf recive

    Catch ex As Exception

    MsgBox(ex.ToString)

    End Try

    Next

    End Sub



    End Class</pre>


    در سی شارپ

    کد:

    کد:
    namespace program

    {

    using SDK;

    public class plugin_manager

    {

    public IPlugin_Collection cPicPlugins = new IPlugin_Collection();

    public event reciveMessageEventHandler reciveMessage;

    public delegate void reciveMessageEventHandler(string msg, IPlugin IPlugin);



    private void recive(string msg, IPlugin IPlugin)

    {

    if (reciveMessage != null)

    {

    reciveMessage(msg, IPlugin);

    }

    }





    public void load_plugin()

    {

    Microsoft.Win32.RegistryKey r;

    Microsoft.Win32.RegistryKey r1;

    Microsoft.Win32.RegistryKey r2;

    string[] s;



    string pStrPath=null ;

    string pStrType=null ;

    r = Microsoft.Win32.Registry.LocalMachine;

    r1 = r.OpenSubKey("SOFTWARE\\my program\\plug in", false);

    s = r1.GetSubKeyNames();

    foreach (string s1 in s)

    {

    try {

    r2 = r1.OpenSubKey(s1);

    pStrPath = (string )r2.GetValue("path");

    pStrType = (string)r2.GetValue("type");

    }

    catch (Exception ex) {

    }

    try {

    System.Runtime.Remoting.ObjectHandle pObhHandle = Activator.CreateInstanceFrom(pStrPath, pStrType);

    SDK.IPlugin pIpnPlugin = (SDK.IPlugin)pObhHandle.Unwrap();

    cPicPlugins.add(pIpnPlugin);

    pIpnPlugin.SendMessage += recive;

    }

    catch (Exception ex) {

    System.Windows.Forms.MessageBox.Show(ex.ToString());

    }

    }

    }



    }



    }</pre>


    توضیحات کلاس

    متد load_plugin از اسمش داد میزنه که رای لود پلاگین ها بکار می رود.در
    این تابع اطلاعات از ریجیستری خوانده شده و dll پلاگین ها لود می شود. لود
    این dll ها در این دو خط کد است.

    وی بی

    کد:

    کد:
    Dim pObhHandle As Runtime.Remoting.ObjectHandle = Activator.CreateInstanceFrom(pStrPath, pStrType)

    Dim pIpnPlugin As SDK.IPlugin = CType(pObhHandle.Unwrap, SDK.IPlugin)</pre>


    سی شارپ

    کد:

    کد:
    System.Runtime.Remoting.ObjectHandle pObhHandle = Activator.CreateInstanceFrom(pStrPath, pStrType);

    SDK.IPlugin pIpnPlugin = (SDK.IPlugin)pObhHandle.Unwrap();</pre>


    پس از لود انها را در مجوعه پلاگین قرار می دهیم.

    cPicPlugins مجموعه پلاگین هایه ماست.

    رویداد reciveMessage این رویداد واسطه ای بین رویداد sendmessage یک پلاگین و فرم اصلی برنامه است.

    تابع recive هم این رویداد را فرا می خواند.

    کدهای فرم اصلی

    با وی بی

    کد:

    کد:
    Dim WithEvents p As New plugin_manager

    Dim plug As SDK.IPlugin

    Dim a As Integer



    Private Sub p_reciveMessage(ByVal msg As String, ByVal IPlugin As SDK.IPlugin) Handles p.reciveMessage

    If msg = "textbox1" Then

    p.cPicPlugins.item(p.cPicPlugins.indexOf(IPlugin)).GetMessage(TextBox1.Text)

    ElseIf msg = "textbox2" Then

    p.cPicPlugins.item(p.cPicPlugins.indexOf(IPlugin)).GetMessage(TextBox2.Text)

    End If

    End Sub



    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    p.load_plugin()

    For a = 0 To p.cPicPlugins.Count - 1

    plug = p.cPicPlugins.item(a)

    If Not plug.menu Is Nothing Then

    Me.MenuStrip1.Items.AddRange(p.cPicPlugins.item(a).menu)

    End If

    Next



    End Sub</pre>


    با سی شارپ

    کد:

    کد:
    namespace program

    {

    public partial class Form1 : Form

    {

    plugin_manager p;

    SDK.IPlugin plug;

    int a;

    public Form1()

    {

    InitializeComponent();

    p = new plugin_manager();

    p.reciveMessage += new plugin_manager.reciveMessageEventHandler(p_reciveMessage);

    }



    void p_reciveMessage(string msg, SDK.IPlugin IPlugin)

    {

    if (msg == "textbox1") { p.cPicPlugins[p.cPicPlugins.indexOf(IPlugin)].GetMessage(TextBox1.Text); }

    if (msg == "textbox2") { p.cPicPlugins[p.cPicPlugins.indexOf(IPlugin)].GetMessage(TextBox2.Text); }



    }



    private void Button1_Click(object sender, EventArgs e)

    {

    p.load_plugin();

    for (a = 0; a < p.cPicPlugins.Count; a++) {

    plug = p.cPicPlugins[a];

    if (plug.menu() != null) { this.MenuStrip1.Items.AddRange(p.cPicPlugins[a].menu()); }

    }

    }

    }

    }</pre>


    تو ضیحات کد

    متغییر ها که نیاز به توضیح ندارند اما دو تابع رویداد اولی تابع
    p_reciveMessage که وقتی اطلاعاتی از پلاگین ها می رسد اجرا می شود. در
    این تابع ما پس از کردن پیغام پاسخ مناسب را می فرستیم مثلا در اینجا یک
    پلاگین با فرستادن پیغام textbox1 ما برای ان مقدار text این کنترل را می
    فرستیم.

    رویداد کلیک دکمه لود پلاگین ها با اجرا شدن این تابع پلاگین ها لود و منو های داخل ان در منو اصلی برنامه ادغام می شود.
    لایه پلاگین

    ابتدا یک پروژه از نوع application ایجاد کنید.سپس در قسمت خصوصیات پروژه
    نوع پروژه را از application به class library تغییر دهید چون باید خروجی
    ما حتما یک dll باشد.سپس پروژه اولون یعنی IPlugin را به رفرنس های برنامه
    اضافه کنید

    این پروژه یک کلاس مهم بنام my_plugin دارد.این کلاس براساس Interface IPlugin که در پروژه اول نوشتیم ایجاد می شود.

    کد وی بی

    کد:

    کد:
    Imports sdk



    Public Class my_plugin

    Implements IPlugin

    Dim WithEvents f As Form1

    Public Sub New()

    f = New Form1

    End Sub

    #Region "Private declarations"



    Private Const IPlugin_name As String = "my_plugin"



    #End Region



    #Region "Property interface"



    Public Property Name() As String Implements IPlugin.Name

    Get

    Return (IPlugin_name)

    End Get

    Set(ByVal value As String)



    End Set

    End Property



    Public Property menu() As Windows.Forms.ToolStripItemCollection Implements IPlugin.menu

    Get

    Return (f.MenuStrip1.Items)

    End Get

    Set(ByVal value As Windows.Forms.ToolStripItemCollection)



    End Set

    End Property

    Dim message As String

    Public Sub GetMessage(ByVal msg As String) Implements IPlugin.GetMessage

    message = msg

    End Sub



    Event SendMessage(ByVal msg As String, ByVal IPlugin As IPlugin) Implements IPlugin.SendMessage





    Public Sub About() Implements IPlugin.About



    Dim f As New about

    f.ShowDialog()

    End Sub



    Public Sub DisplayPlugForm() _

    Implements IPlugin.DisplayPlugForm

    f.Show()

    End Sub



    #End Region





    Private Sub f_menu1_click() Handles f.menu1_click

    RaiseEvent SendMessage("textbox1", Me)

    f.a = Int(Message)

    RaiseEvent SendMessage("textbox2", Me)

    f.b = Int(Message)

    End Sub

    End Class</pre>


    کد سی شارپ

    کد:

    کد:
    using System;

    using System.Collections.Generic;

    using System.Text;

    using SDK;

    namespace my_plugin

    {

    class my_plugin :IPlugin

    {

    #region IPlugin Members

    const string IPlugin_name = "my_plugin";

    string message=null ;

    Form1 f ;

    public string name()

    {

    return IPlugin_name;

    }



    public void About()

    {

    about f = new about();

    f.ShowDialog();

    }



    public void DisplayPlugForm()

    {

    f.Show();

    }



    public void GetMessage(string msg)

    {

    message = msg;

    }



    public event SDK.EventHandler SendMessage;



    public System.Windows.Forms.ToolStripItemCollection menu()

    {

    return f.menuStrip1.Items ;

    }



    #endregion

    public my_plugin() {

    f = new Form1();

    f.menu1_click += new Form1.menu1_click_eventhandler(f_menu1_click);

    }



    void f_menu1_click()

    {

    SendMessage("textbox1", this);

    f.a = Convert.ToInt32(message);

    SendMessage("textbox2", this);

    f.b = Convert.ToInt32(message);

    }

    }

    }</pre>


    توضیحات کد

    خاصیت name و menu اولی نام پلاگین را بر می گرداند دومی هم menu فرم اصلی
    ]چون فرصت نداشتم منو با کد تعریف کنم یک منو داخل فرم گذاشتم بعد ایتم
    های ان را به عنوان منو می فرستم اما شما در برنامه هاتون این کار را
    نکنید[

    تابع GetMessage هم اطلاعات در یافتی از برنامه اصلی را در متغییر رشته ای بنام message ذخیره می کند.

    رویداد SendMessage فکر نکنم نیاز به توضیح داشته باشد.

    تابع های About و DisplayPlugForm هم به ترتیب فرم های توضیحات برنامه و فرم اصلی را نمایش می دهد.

    تابع رویداد f_menu1_click این هم وقتی اجرا می شود که منو روی فرم اصلی کلیک شود.

    این تابع پبغامی را به برنامه اصلی فرستاده و از برنامه اصلی مقدار کنترل
    هلی تکس با کس را می کند و سپس این مقادبر را در متغییرهایی که در فرم
    اصلی تعریف کردیم ذخیره می کند.

    می رسیم به کد فرم اصلی

    با وی بی

    کد:

    کد:
    Public Class Form1

    Public a, b As Integer

    Public Event menu1_click()

    Private Sub ضربToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ضربToolStripMenuItem.Click

    RaiseEvent menu1_click()

    Me.Show()

    Label1.Text = "حاصلضرب اعداد شما برابر" + (a * b).ToString

    End Sub



    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Me.MenuStrip1.Hide()

    End Sub

    End Class</pre>


    با سی شارپ

    کد:

    کد:
    namespace my_plugin

    {

    public partial class Form1 : Form

    {

    public delegate void menu1_click_eventhandler();

    public Form1()

    {

    InitializeComponent();

    }



    public event menu1_click_eventhandler menu1_click;

    private void ضربToolStripMenuItem_Click(object sender, EventArgs e)

    {

    menu1_click();

    this.Show();

    this.label1.Text = "حاصلضرب اعداد شما برابر" + (a * b).ToString();

    }

    public int a, b;

    private void Form1_Load(object sender, EventArgs e)

    {

    this.menuStrip1.Hide();

    }

    }

    }</pre>


    توضیحات کد

    دو متغییر a,b که قبلا توضیح دادم رویداد menu1_click هم که رویدادی است
    که با فشرده شدن منو فرا خوانده می شود و بقیه کدها هم فکر نکنم نیاز به
    توضیح باشد.

    اجرای برنامه مثال

    ابتدا شما فایل ریجیستری برنامه را با نام reg.reg را اجرا کنید تا کلید و مقادیر ریجیستری ایجاد شود و سپس برنامه را اجرا نمایید