PDA

View Full Version : حرفه ای: صدا زدن evant button_click از exe ای دیگر



sadaf_
یک شنبه 06 اسفند 1391, 10:15 صبح
سلام
چطوری می شه در پروژه a یک evant از پروژه b را صدا زد؟
ممنون

vistacali
یک شنبه 06 اسفند 1391, 11:45 صبح
مثلا چه eventy رو میخوای صدا بزنی

Himalaya
یک شنبه 06 اسفند 1391, 11:54 صبح
سلام.
چند تا راه داره
1. شیوه جواد بازی :لبخند: تو برنامه دوم میتونید ایونت مثلا دکمه رو به صورت Public تعریف کنید و فایل exe برنامه رو به عنوان رفرنس اضافه کنید به پروژه و بقیه ماجرا
2. از Reflection استفاده کنید. خود این هم به دو صورت امکان پذیره
الف. ایونتی رو که تو روش 1 Public کردید رو به حالت قبل برگردونید (Private) و بعد یک تابع Public برای صدا کردن این ایونت بنویسید و از برنامه 1 این تابع رو صدا بزنید. لازمش اینه که از dotnet 4 استفاده کنید به خاطر استفاده از نوع dynamic (روش نیمه جواد)
ب. کلا Public کردن ها رو بزارید کنار و از متد Invoke برای صدا زدن تابع استفاه کنید. حالت الف و ب تا یه قسمت کداشون مشترکه.

1.

var frm = new Form2();
frm.button1_Click(null, null); //button1_Click is public in Form2 in assembly WindowsFormsApplication2

2. من مسیر مستقیم دادم. برای دسترسی به مسیر برنامه دوم هر جور که خودتون میخواید عمل کنید

// load dll or exe from path
var app2Path = Path.GetFullPath("..\\..\\..\\WindowsFormsApplication2\\bin\\Debug\\ WindowsFormsApplication2.exe");
var asm = Assembly.LoadFile(app2Path);

// find Form2 class in assembly WindowsFormsApplication2
var frmInApp2 = asm.GetTypes().FirstOrDefault(t => String.Compare(t.Name, "Form2", StringComparison.OrdinalIgnoreCase) == 0);
if (frmInApp2 == null) return;

///////// الف //////////
dynamic frm = Activator.CreateInstance(frmInApp2);
frm.PerformClick();
///////// الف //////////


///////// ب //////////
// find button2_Click event in Form2 in assembly WindowsFormsApplication2
var clickEvent = frmInApp2.GetMethod("button2_Click", BindingFlags.NonPublic | BindingFlags.Instance);
// param1 is classInstance and param2 is method paramerers
clickEvent.Invoke(Activator.CreateInstance(frmInAp p2), new object[] { null, null });
///////// ب //////////

البته یه پست هم زدید با این عنوان

اجرای پروژه های دیگر در یک پروژهکه برای نمایش یکی از فرمهای پروژه 2 از داخل پروژه 1، از روش ب استفاه کنید. خطوط زیر یه مقدار تغییر میکنن

// find Form2 class in assembly WindowsFormsApplication2
var frmInApp2 = asm.GetTypes().FirstOrDefault(t => String.Compare(t.Name, "Form2", StringComparison.OrdinalIgnoreCase) == 0 &&
t.BaseType == typeof(Form));
if (frmInApp2 == null) return;

///////// الف //////////
var frm = (Form)Activator.CreateInstance(frmInApp2);
frm.Show();
///////// الف //////////

sadaf_
دوشنبه 07 اسفند 1391, 09:59 صبح
سلام.
چند تا راه داره
1. شیوه جواد بازی :لبخند: تو برنامه دوم میتونید ایونت مثلا دکمه رو به صورت Public تعریف کنید و فایل exe برنامه رو به عنوان رفرنس اضافه کنید به پروژه و بقیه ماجرا
2. از Reflection استفاده کنید. خود این هم به دو صورت امکان پذیره
الف. ایونتی رو که تو روش 1 Public کردید رو به حالت قبل برگردونید (Private) و بعد یک تابع Public برای صدا کردن این ایونت بنویسید و از برنامه 1 این تابع رو صدا بزنید. لازمش اینه که از dotnet 4 استفاده کنید به خاطر استفاده از نوع dynamic (روش نیمه جواد)
ب. کلا Public کردن ها رو بزارید کنار و از متد Invoke برای صدا زدن تابع استفاه کنید. حالت الف و ب تا یه قسمت کداشون مشترکه.

1.

var frm = new Form2();
frm.button1_Click(null, null); //button1_Click is public in Form2 in assembly WindowsFormsApplication2

2. من مسیر مستقیم دادم. برای دسترسی به مسیر برنامه دوم هر جور که خودتون میخواید عمل کنید

// load dll or exe from path
var app2Path = Path.GetFullPath("..\\..\\..\\WindowsFormsApplication2\\bin\\Debug\\ WindowsFormsApplication2.exe");
var asm = Assembly.LoadFile(app2Path);

// find Form2 class in assembly WindowsFormsApplication2
var frmInApp2 = asm.GetTypes().FirstOrDefault(t => String.Compare(t.Name, "Form2", StringComparison.OrdinalIgnoreCase) == 0);
if (frmInApp2 == null) return;

///////// الف //////////
dynamic frm = Activator.CreateInstance(frmInApp2);
frm.PerformClick();
///////// الف //////////


///////// ب //////////
// find button2_Click event in Form2 in assembly WindowsFormsApplication2
var clickEvent = frmInApp2.GetMethod("button2_Click", BindingFlags.NonPublic | BindingFlags.Instance);
// param1 is classInstance and param2 is method paramerers
clickEvent.Invoke(Activator.CreateInstance(frmInAp p2), new object[] { null, null });
///////// ب //////////

البته یه پست هم زدید با این عنوان
که برای نمایش یکی از فرمهای پروژه 2 از داخل پروژه 1، از روش ب استفاه کنید. خطوط زیر یه مقدار تغییر میکنن

// find Form2 class in assembly WindowsFormsApplication2
var frmInApp2 = asm.GetTypes().FirstOrDefault(t => String.Compare(t.Name, "Form2", StringComparison.OrdinalIgnoreCase) == 0 &&
t.BaseType == typeof(Form));
if (frmInApp2 == null) return;

///////// الف //////////
var frm = (Form)Activator.CreateInstance(frmInApp2);
frm.Show();
///////// الف //////////

دوست عزیز این روش درست کار می کنه اما یک مشکلی هست
اینکه پروژه دوم باید اجرا بشه الببته کاربر نمی فهمه که اچرا شده و فرم مورد نظر را نمایش می دم
چطوری اول پروژه را اجرا کنم و سپس همون رویداد را صدا بزنم؟

sadaf_
دوشنبه 07 اسفند 1391, 20:15 عصر
دوستان لطفا راهنمایی کنید

Himalaya
دوشنبه 07 اسفند 1391, 21:18 عصر
سلام.


دوست عزیز این روش درست کار می کنه اما یک مشکلی هست
اینکه پروژه دوم باید اجرا بشه الببته کاربر نمی فهمه که اچرا شده و فرم مورد نظر را نمایش می دم
چطوری اول پروژه را اجرا کنم و سپس همون رویداد را صدا بزنم؟

شما هر فرمی از پروژه دوم رو که بخواید، میتونید از طریق پروژه اول اجرا کنید. حتی بدون اجرای فرم میتونید توابعش رو فراخوانی کنید.
کافیه نمونه سازی بشه از اون کلاس مورد نظر. حالا تو ادامه اگه کلاس مربوط به فرم بود، یا نمایشش میدید یا توابعش رو اجرا میکنید.
متوجه نمیشم مشکلت کجاس

sadaf_
سه شنبه 08 اسفند 1391, 13:14 عصر
من امنیت برنامه را در یک کلاس گذاشتم و همچنین ارتباط دیتابیس را هم در کلاسی دیگر
حالا من نیاز دارم ابتدا کلاسها صدا زده بشه و سپس فرم مورد نظرم را لود کنم
در این دستورات شما لود فرم درست کار می کنه اما من نفهمیدم چطوری کلاس را صدا بزنم؟
و نکته دیگر اینکه فرمهای من در هنگام new پارامتر می گیرند یعنی باید یک یا چند مقدار پاس بدم در این روش چطوری مقدار پاس بدم؟
ممنون

Himalaya
سه شنبه 08 اسفند 1391, 14:26 عصر
سلام.
ببین گفتم اصلا فقی نداره کلاس مربوط به فرم باشه یا نباشه. تنها چیزی که مهمه نمونه سازی از رو اون هستش. بعد از نمونه سازی هر بلایی خواستی میتونی سرش بیاری
فرض کن کلاس زیر تو یه پروژه دیگه قرار داره و معادل همون کلاس امنیت شماس، که مشخص میکنه کاربر تو فرم x به دکمه y دسترسی داره یا نه. (کدای نوشته شده فقط واسه تست هستش)


using System;
using System.Collections.Generic;
using System.Linq;

namespace Security
{
public class ClsSecurity
{
private readonly string _btnName;
private readonly string _frmName;
public ClsSecurity(string frmName, string btnName)
{
_frmName = frmName;
_btnName = btnName;
}

public bool AccessToButton()
{
return Access.GetTestAccessList().Any(c => String.Compare(c.FormName, _frmName, StringComparison.OrdinalIgnoreCase) == 0 &&
String.Compare(c.ButtonName, _btnName, StringComparison.OrdinalIgnoreCase) == 0);
}
}

public class Access
{
public string FormName { get; set; }
public string ButtonName { get; set; }

public static List<Access> GetTestAccessList()
{
return new List<Access>
{
new Access{FormName = "Form1", ButtonName = "Button1"},
new Access{FormName = "Form1", ButtonName = "Button2"},
new Access{FormName = "Form1", ButtonName = "Button3"},
new Access{FormName = "Form1", ButtonName = "Button4"},
new Access{FormName = "Form2", ButtonName = "Button1"},
new Access{FormName = "Form2", ButtonName = "Button2"},
};
}
}
}

و تو پروژه اصلی تو یه دکمه کدای زیر رو داریم


var app2Path = Path.GetFullPath("..\\..\\..\\Security\\bin\\Debug\\Security.dll");
var asm = Assembly.LoadFile(app2Path);

var clsSecurity = asm.GetTypes().FirstOrDefault(t => String.Compare(t.Name, "ClsSecurity", StringComparison.OrdinalIgnoreCase) == 0);
if (clsSecurity == null) return;

dynamic instance = Activator.CreateInstance(clsSecurity,new object[] { "Form1", "Button1" });
MessageBox.Show(string.Format("Access To Button1 Is: {0}", instance.AccessToButton()));

اولا که پارامتر دوم تابع CreateInstance میتونه یه آرایه از جنس Object باشه که داره ورودی های Constroctur مورد نظر رو مشخص میکنه (اگه چیزی نزاریم یعنی Constroctur پیش فرض)
دوما اینجا من پروژه دوم رو به صورت ClassLibrary ایجاد کردم، پس تو Assembly.LoadFile مسیر dll رو قرار دادم نه exe (هیچ فرقی نداره. باز نگی واسه من exe هستش. یه کلاس خوب یه کلاسه دیگه، حالا فرقی نداره تو ClassLibrary تعریف شده باشه یا تو WinApp)
اون چیزی هم که تو MessageBox نمایش داده میشه به ازای Button1 مقدار True و به ازای مثلا Button5 مقدار False هستش

sadaf_
پنج شنبه 10 اسفند 1391, 09:08 صبح
با تشکر از karaji333 (http://barnamenevis.org/member.php?53563-karaji333)
حالا من چطوری می تونم exe را اجرا کنم و بعد از اون به فرم هایی که می خوام دسترسی داشته باشم؟
کاربر frmmain را مشاهده نمی کنه
ممنونم

Himalaya
پنج شنبه 10 اسفند 1391, 09:24 صبح
سلام


حالا من چطوری می تونم exe را اجرا کنم و بعد از اون به فرم هایی که می خوام دسترسی داشته باشم؟
کاربر frmmain را مشاهده نمی کنه

نمیدونم چرا اصلا به کدا دقت نمیکنی. به جای Form2 اسم فرمی رو که میخوای (از پروژه دوم) بزار و هر کاری خواستی باهاش انجام بده دیگه :گریه:


// find Form2 class in assembly WindowsFormsApplication2
var frmInApp2 = asm.GetTypes().FirstOrDefault(t => String.Compare(t.Name, "Form2", StringComparison.OrdinalIgnoreCase) == 0 &&
t.BaseType == typeof(Form));
if (frmInApp2 == null) return;

///////// الف //////////
var frm = (Form)Activator.CreateInstance(frmInApp2);
frm.Show();
///////// الف //////////

sadaf_
پنج شنبه 10 اسفند 1391, 09:36 صبح
دقت کردم دوست عزیز فقط می خوام exe اجرا بشه نمی حوام اسم فرم را بدم:لبخندساده:

Himalaya
پنج شنبه 10 اسفند 1391, 10:15 صبح
فقط می خوام exe اجرا بشه نمی حوام اسم فرم را بدم

Process.Start("exe path");