位置:首頁(yè) > 軟件操作教程 > 編程開(kāi)發(fā) > C# > 問(wèn)題詳情

C#程序嵌入DLL的調(diào)用

提問(wèn)人:劉冬梅發(fā)布時(shí)間:2020-10-12
1) ldfs類(lèi)的編寫(xiě):

在項(xiàng)目“Tzb”中新建一個(gè)名為ldfs的類(lèi),意為“l(fā)oad dll from resource”,請(qǐng)注意,在這個(gè)類(lèi)中“resource”不只是嵌入在EXE程序中的資源,它也可以是硬盤(pán)上任意一個(gè)DLL文件,這是因?yàn)閘dfs的類(lèi)中的方法LoadDll有些特別,就是先從程序的內(nèi)嵌的資源中查找需加載的DLL,如果找不到,就查找硬盤(pán)上的。

首先導(dǎo)入所需的命名空間:

using System.IO; // 對(duì)文件的讀寫(xiě)需要用到此命名空間

using System.Reflection; // 使用 Assembly 類(lèi)需用此命名空間

using System.Reflection.Emit; // 使用 ILGenerator 需用此命名空間

聲明一靜態(tài)變量MyAssembly:

// 記錄要導(dǎo)入的程序集

static Assembly MyAssembly;

添加LoadDll方法:

private byte[] LoadDll(string lpFileName)

{

Assembly NowAssembly = Assembly.GetEntryAssembly();

Stream fs=null;

try

{// 嘗試讀取資源中的 DLL

fs = NowAssembly.GetManifestResourceStream(NowAssembly.GetName().Name+"."+lpFileName);

}

finally

{// 如果資源沒(méi)有所需的 DLL ,就查看硬盤(pán)上有沒(méi)有,有的話就讀取

if (fs==null&&!File.Exists(lpFileName)) throw(new Exception(" 找不到文件 :"+lpFileName));

else if(fs==null&&File.Exists(lpFileName))

{

FileStream Fs = new FileStream(lpFileName, FileMode.Open);

fs=(Stream)Fs;

}

}

byte[] buffer = new byte[(int) fs.Length];

fs.Read(buffer, 0, buffer.Length);

fs.Close();

return buffer; // 以 byte[] 返回讀到的 DLL

}

添加UnLoadDll方法來(lái)卸載DLL:

public void UnLoadDll()

{// 使 MyAssembly 指空

MyAssembly=null;

}

添加Invoke方法來(lái)進(jìn)行對(duì)DLL中方法的調(diào)用,其原理大體上和“Form1.cs”中的方法Invoke相同,不過(guò)這里用的是“Assembly.Load”,而且用了靜態(tài)變量MyAssembly來(lái)保存已加載的DLL,如果已加載的話就不再加載,如果還沒(méi)加載或者已加載的不同現(xiàn)在要加載的DLL就進(jìn)行加載,其代碼如下所示:

public object Invoke(string lpFileName,string Namespace,string ClassName,string lpProcName,object[] ObjArray_Parameter)

{

try

{// 判斷 MyAssembly 是否為空或 MyAssembly 的命名空間不等于要調(diào)用方法的命名空間,如果條件為真,就用 Assembly.Load 加載所需 DLL 作為程序集

if(MyAssembly==null||MyAssembly.GetName().Name!=Namespace)

MyAssembly=Assembly.Load(LoadDll(lpFileName));

Type[] type=MyAssembly.GetTypes();

foreach(Type t in type)

{

if(t.Namespace==Namespace&&t.Name==ClassName)

{

MethodInfo m=t.GetMethod(lpProcName);

if(m!=null)

{// 調(diào)用并返回

object o=Activator.CreateInstance(t);

return m.Invoke(o,ObjArray_Parameter);

}

else

System.Windows.Forms.MessageBox.Show(" 裝載出錯(cuò) !");

}

}

}

catch(System.NullReferenceException e)

{

System.Windows.Forms.MessageBox.Show(e.Message);

}

return (object)0;

}

2) ldfs類(lèi)的使用:

1. 把CsCount.dll作為“嵌入的資源”添加到項(xiàng)目“Tzb”中。

2. 向“Form1”窗體中添加兩個(gè)按鈕,Name和Text屬性分別為“B7”、“l(fā)dfs.Invoke調(diào)用count”;“B8”、“UnLoadDll”,并將它們調(diào)整到適當(dāng)大小和位置。

3. 打開(kāi)“Form1.cs”代碼視圖,添加一個(gè)ldfs實(shí)例:

// 添加一個(gè) ldfs 實(shí)例 tmp

private ldfs tmp=new ldfs();

4. 在“Form1.cs[設(shè)計(jì)]”視圖中雙擊按鈕B7,在“B1_Click”方法體內(nèi)添加如下代碼:

// 調(diào)用 count(0), 并使用期提示框顯示其返回值

MessageBox.Show(" 這是您第 "+tmp.Invoke("CsCount.dll","CsCount","Class1","count",new object[]{(int)0}).ToString()+" 次點(diǎn)擊此按鈕。 "," 挑戰(zhàn)杯 ");

5. 在“Form1.cs[設(shè)計(jì)]”視圖中雙擊按鈕B7,在“B1_Click”方法體內(nèi)添加如下代碼:

// 卸載 DLL

tmp.UnLoadDll();

6. “F5”運(yùn)行該程序,并先點(diǎn)擊按鈕B7三次,接著點(diǎn)擊按鈕B8,最后再點(diǎn)擊按鈕B7,此時(shí)發(fā)現(xiàn)又開(kāi)始重新計(jì)數(shù)了,情況和“dld類(lèi)的使用”類(lèi)似,也就是也實(shí)現(xiàn)了DLL的動(dòng)態(tài)裝載與卸載了。

繼續(xù)查找其他問(wèn)題的答案?

相關(guān)視頻回答
回復(fù)(0)
返回頂部