PDA

View Full Version : سوال: استفاده از فایل resource به عنوان reference



Aghil61
چهارشنبه 02 اسفند 1391, 18:27 عصر
سلام
من در یک پروژه با استفاده از Add Reference یک فایل dll رو add کردم. حالا اگه بخوام فایل exe رو انتقال بدم، باید فایل dll رو هم همراه با اون انتقال بدم. آیا میشه dll رو resource کنم و از اون به عنوان reference استفاده کنم. چند تا تاپیک در این مورد دیدم اما به نتیجه درستی نرسیده بود. لطفا راهنمایی کنید.

danialafshari
چهارشنبه 02 اسفند 1391, 18:34 عصر
سلام دوست عزیز

می تونی با برنامه ای که Microsoft ارائه داده می تونی انجامش بدی :
لینک (http://www.microsoft.com/downloads/details.aspx?FamilyID=22914587-B4AD-4EAE-87CF-B14AE6A939B0&displaylang=en)
نام برنامه ilmerge است
آموزش :
در آدرسی که دادم دکمه Download رو بزنید و Ilmerge رو Save بفرمایید.

خوب حالا نصبش بکنید و یک کپی از Ilmerge.exe نصب شده رو هم در داخل شاخه Winnt کپی کنید.

خوب دیگه حالا همه چی برای هنر نمایی شما حاضر!

پروژتون رو در حالت Debug قرار بدید و بی زحمت Rebuild بفرمایید

پس از رفتن به قسمت Command Prompt به اون دایرکتوری که پروژتون قرار داره و در دایرکتوری bin\Debug تشریف ببرید و این عبارت رو تایپ بفرمایید.


Ilmerge /out:NewName.exe PrjFile.exe DllFile.dll

NewName: اسم جدید فایل اجرایی برنامتون هست.

PrjFile: اسم فایل اجرایی برنامتون که دایرکتوری Debug قرار داره

DllFile.dll: اسم Dll محبوب شماست که قرار مال خود خودت باشه

حالا یه مثال که دیگه کامل قضیه حل بشه:

تصور کن که یه برنامه نوشتی به اسم Convertor و از یک Dll به نام Exchange برای تبدیل کردن واحد های مختلف پول که دست بر قضا یکی از کارای قشنگتم بوده استفاده کردی

عبارتی که در Command Prompt باید بنویسی این میشه


D:\MyProject\bin\Release>ilmerge /out:Mohammad.exe Convertor.exe Exchange.dll

موفق باشی

Aghil61
چهارشنبه 02 اسفند 1391, 19:04 عصر
خیلی ممنون
من این روش رو در یه پست دیگه که توسط خودتون ایجاد شده دیدم و انجام دادم. اما با کلی خطا مواجه شدم.

100332

لطفا راهنمایی کنید که این خطاها مربوط به چیه.
آیا بدون استفاده از نرم افزارهای جانبی و با استفاده از ویژوال استودیو یا کدنویسی میشه این کار رو انجام داد؟

danialafshari
چهارشنبه 02 اسفند 1391, 20:13 عصر
من خودم با روش بالا تست کردم و نتیجه گرفتم

مهرداد صفا
پنج شنبه 03 اسفند 1391, 01:24 صبح
آیا بدون استفاده از نرم افزارهای جانبی و با استفاده از ویژوال استودیو یا کدنویسی میشه این کار رو انجام داد؟


سلام.
بله. البته این کار در vb.net به دلیل پشتیبانی از late binding بسیار ساده تر صورت می گیرد اما در هر صورت برای این کار مراحل زیر را دنبال کنید:

1- یک ClassLibrary بسازید به نام ClassLibrary1 دارای یک کلاس به نام Class1 که خود دارای یک constructer یا سازنده و یک متود به نام

public void MessageBox(string Message)
است. این متود مقدار آرگومنت message را در یک جعبه پیغام نمایش می دهد.
2- یک پروژه Windows Forms Application جدید ایجاد کنید.
3- از منوی Project>add Existing item فایل ClassLibrary1.dll را که قبلا آماده کردید به پروژه اضافه کنید.
4- از منوی view>solution explorer را باز کرده روی ClassLibrary1.dll راست کلیک کنید و گزینه properties را انتخاب کنید.
5- گزینه build action را روی embedded resource قرار دهید.
6- قسمت کدهای form1.cs را باز کنید و در ابتدای آن کد زیر را اضافه کنید:

using System.Reflection;
using System.IO;
namespace WindowsFormsApplication1


7- در قسمت سازنده کلاس با استفاده از متود Assembly.GetExecutingAssembly اسمبلی در حال اجرا را به دست بیاورید و با استفاده از متود Assembly.GetManifestResourceStream یک Stream از کتابخانه ای که به resource اضافه کرده بودید بگیرید و در یک متغیر نگهدارید:

Stream ClassLibrary1Stream = Assembly.GetExecutingAssembly().GetManifestResourc eStream("WindowsFormsApplication1.ClassLibrary1.dll");
8- stream را در یک آرایه از byte بخوانید:

byte[] bytes = new byte[ClassLibrary1Stream.Length];
ClassLibrary1Stream.Read(bytes, 0, bytes.Length - 1);
9- حالا با ارسال آرایه به متود Assembly.Load کتابخانه را لود کنید و مقدار را در یک Assembly نگهدارید:

Assembly ClassLibrary1 = Assembly.Load(bytes);
10- با استفاده از متود Assembly.GetTypes تمام Type های اسمبلی را گرفته و از میان آنها "Class1" را انتخاب کنید:

Type t = (from Type type in ClassLibrary1.GetTypes() where type.Name == "Class1" select type).First();
11- در این مرحله با استفاده از متود Type.GetConstructers تمام سازنده های کلاس Class1 را به دست بیاورید، همانطور که در مرحله 1 دیدید این کلاس تنها یک سازنده دارد که هیچ آرگومنتی در یافت نمیکند، پس به اولین عضو از این آرایه اشاره کنید و با استفاده از متود Invoke آن را اجرا کنید. متود Invoke سازنده کلاس Class1 را اجرا می کند و مقدار برگشتی آن یک object از این کلاس است، این متود همچنین یک آرایه از object را به عنوان آرگومنتهای متود سازنده دریافت می کند که در اینجا چون سازنده کلاس Class1 هیچ آرگومنتی ندارد به ازای این آرگومنت null ارسال می شود:

object class1 = t.GetConstructors()[0].Invoke(null);
12- با ارسال نام متودی که قصد اجرا کردن آن را دارید ( در اینجا MessageBox) به متود Type.GetMethod یک MethodInfo به دست می آورید. متود MethodInfo.Invoke وظیفه اجرا کردن متود (MessageBox) را دارد، متود Invoke دو آرگومنت دریافت میکند که اولی یک instance از کلاسی است که متود به آن تعلق دارد (این آرگومنت در مورد متودهای static برابر با null است) و دومی یک آرایه از object است که پارامترهایی هستند که باید به متود مورد نظر ارسال شوند، در صورتی که متود آرگومنتی ندارد این آرگومنت برابر null خواهد بود:

t.GetMethod("MessageBox").Invoke(class1, new object[1] { "hello World" });
و خواهید دید که متود Class1.MessageBox از کتابخانه ClassLibrary1 که در RESOURCE برنامه قرار دارد اجرا می شود. البته همانطور که گفتم در VB نیازی به Invoke کردن متودها به این صورت نداریم و می توانیم به متودها و خصوصیات به راحتی و مانند یک شی معمولی دسترسی داشته باشیم.
کد کلاس form1 به طور کامل:

//in the name of god
//صل الله علی محمد و آله

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Stream ClassLibrary1Stream = Assembly.GetExecutingAssembly().GetManifestResourc eStream("WindowsFormsApplication1.ClassLibrary1.dll");
byte[] bytes = new byte[ClassLibrary1Stream.Length];
ClassLibrary1Stream.Read(bytes, 0, bytes.Length - 1);
Assembly ClassLibrary1 = Assembly.Load(bytes);
Type t = (from Type type in ClassLibrary1.GetTypes() where type.Name == "Class1" select type).First();
object class1 = t.GetConstructors()[0].Invoke(null);
t.GetMethod("MessageBox").Invoke(class1, new object[1] { "hello World" });
}
}
}


باز هم اگر سوالی در موردش داشتید بفرمایید.

sadeghjun
شنبه 23 شهریور 1392, 13:08 عصر
سلام
من از کامپوننت Ionic.Zip در برنامه خودم اسفاده میکنم . با استفاده از روش شما چه جوری باید از این تابع استفاده کنم؟؟؟

مثلا یه تابع دارم که با استفاده از کامپوننت فایل های زیپ رو باز میکنه:

private void unzip()
{

using (var zip = Ionic.Zip.ZipFile.Read("file address"))
{
zip.Password = "123";
zip.ExtractAll("destination address");
}
}

کامپوننت Ionic
110665

مهرداد صفا
یک شنبه 24 شهریور 1392, 00:53 صبح
سلام
من از کامپوننت Ionic.Zip در برنامه خودم اسفاده میکنم . با استفاده از روش شما چه جوری باید از این تابع استفاده کنم؟؟؟

مثلا یه تابع دارم که با استفاده از کامپوننت فایل های زیپ رو باز میکنه:

private void unzip()
{

using (var zip = Ionic.Zip.ZipFile.Read("file address"))
{
zip.Password = "123";
zip.ExtractAll("destination address");
}
}

کامپوننت Ionic
110665

با سلام.
بعد از اضافه کردن فایل به ReSource:

//بسم الله الرحمن الرحیم
//اللهم صل علی محمد و آل محمد

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
System.IO.Stream Ionic = System.Reflection.Assembly
.GetExecutingAssembly().GetManifestResourceStream("WindowsFormsApplication1.Ionic.Zip.dll");
byte[] bytes = new byte[Ionic.Length];
Ionic.Read(bytes, 0, bytes.Length - 1);
System.Reflection.Assembly Ionic_Zip = System.Reflection.Assembly.Load(bytes);
object ZipFile = Ionic_Zip.GetTypes().Where(t => t.Name == "ZipFile").First()
.GetMethod("Read",new Type[]{typeof( string)}).Invoke(null, new object[] { @"e:\temp\test2.zip" });
ZipFile.GetType().GetProperty("Password").SetValue(ZipFile, "", null);
ZipFile.GetType().GetMethod("ExtractAll", new Type[]{typeof(string)}).Invoke(ZipFile,new object[]{ "e:\\temp\\test2.wav"} );


}
}
}


و در vb.net:

Dim Ionic = Reflection.Assembly.GetExecutingAssembly.GetManife stResourceStream("WindowsApplication1.Ionic.Zip.dll")
Dim bytes() = New Byte(Ionic.Length) {}
Ionic.Read(bytes, 0, bytes.Length)
Activator.CreateInstance(Reflection.Assembly.Load( bytes).GetTypes.Where(Function(t) t.Name = "ZipFile").First).Read("e:\temp\test2.zip").ExtractAll("e:\temp\test2.wav")

sadeghjun
یک شنبه 24 شهریور 1392, 13:01 عصر
سلام
ممنون
ولی بازم خطا داره

تصویر خطا:
http://s1.picofile.com/file/7936897525/assemERRor.jpg