C#程序实现动态调用DLL的研究

C#程序实现动态调用DLL的研究

日期:2006-11-29 12:08:04  点击:0  作者:  来源:站长资讯

数据挖掘工具

AssemblyBuilder MyAssemblyBuilder =AppDomain.CurrentDomain.DefineDynamicAssembly(MyAssemblyName,AssemblyBuilderAccess.Run);

数据挖掘实验室

ModuleBuilder MyModuleBuilder =MyAssemblyBuilder.DefineDynamicModule("InvokeDll");

// 定义要调用的方法 , 方法名为“ MyFun ”,返回类型是“ Type_Return ”参数类型是“ TypeArray_ParameterType ” 数据挖掘工具

MethodBuilder MyMethodBuilder =MyModuleBuilder.DefineGlobalMethod("MyFun",MethodAttributes.Public| MethodAttributes.Static,Type_Return,TypeArray_ParameterType);

数据挖掘研究院

// 获取一个 ILGenerator ,用于发送所需的 IL

ILGenerator IL = MyMethodBuilder.GetILGenerator();

int i; 数据挖掘交友

for (i = 0; i < ObjArray_Parameter.Length; i++) 数据挖掘交友

{// 用循环将参数依次压入堆栈

switch (ModePassArray_Parameter[i])

{

case ModePass.ByValue:

IL.Emit(OpCodes.Ldarg, i);

数据挖掘论坛

break;

数据挖掘研究院

case ModePass.ByRef: 数据挖掘研究院

IL.Emit(OpCodes.Ldarga, i); 数据挖掘研究院

break; 数据挖掘实验室

default: 数据挖掘实验室

throw(new Exception(" 第 " +(i+1).ToString() + " 个参数没有给定正确的传递方式 ." ) );

数据挖掘实验室

}

数据挖掘研究院

}

数据挖掘实验室

if (IntPtr.Size == 4) {// 判断处理器类型

数据挖掘交友

IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32()); 数据挖掘交友

}

else if (IntPtr.Size == 8)

数据挖掘论坛

{ 数据挖掘论坛

IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());

}

数据挖掘交友

else

{

数据挖掘实验室

throw new PlatformNotSupportedException();

数据挖掘论坛

}

数据挖掘实验室

IL.EmitCalli(OpCodes.Calli,CallingConvention.StdCall,Type_Return,TypeArray_ParameterType);

IL.Emit(OpCodes.Ret); // 返回值

数据挖掘交友

MyModuleBuilder.CreateGlobalFunctions(); 数据挖掘论坛

// 取得方法信息 数据挖掘研究院

MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("MyFun"); 数据挖掘论坛

return MyMethodInfo.Invoke(null, ObjArray_Parameter);// 调用方法,并返回其值

数据挖掘论坛

} 数据挖掘工具

 

         Invoke方法的第二个版本,它是调用了第一个版本的: 数据挖掘论坛

/// <summary> 数据挖掘实验室

/// 调用所设定的函数

/// </summary>

/// <param name="IntPtr_Function"> 函数指针 </param>

数据挖掘论坛

/// <param name="ObjArray_Parameter"> 实参 </param> 数据挖掘论坛

/// <param name="TypeArray_ParameterType"> 实参类型 </param>

数据挖掘实验室

/// <param name="ModePassArray_Parameter"> 实参传送方式 </param> 数据挖掘实验室

/// <param name="Type_Return"> 返回类型 </param> 数据挖掘实验室

/// <returns> 返回所调用函数的 object</returns> 数据挖掘研究院

public object Invoke(IntPtr IntPtr_Function,object[] ObjArray_Parameter,Type[] TypeArray_ParameterType,ModePass[] ModePassArray_Parameter,Type Type_Return) 数据挖掘工具

{

数据挖掘交友

// 下面 2 个 if 是进行安全检查 , 若不能通过 , 则抛出异常

数据挖掘工具

if(hModule==IntPtr.Zero)

数据挖掘论坛

throw(new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !"));

数据挖掘实验室

if(IntPtr_Function==IntPtr.Zero) 数据挖掘论坛

throw(new Exception(" 函数指针 IntPtr_Function 为空 !" ) );

数据挖掘交友

farProc=IntPtr_Function;

数据挖掘工具

return Invoke(ObjArray_Parameter,TypeArray_ParameterType,ModePassArray_Parameter,Type_Return); 数据挖掘交友

} 数据挖掘论坛

 

数据挖掘工具

  数据挖掘交友

2)        dld类的使用: 数据挖掘交友

1. 打开项目“Tzb”,向“Form1窗体中添加三个按钮。Name Text属性分别为 B3、“用LoadLibrary方法装载Count.dll”,“B4、“调用count方法”,“B5、“卸载Count.dll”,并调整到适当的大小及位置

2. 在“Form1cs[设计]”视图中双击按钮B3,在“B3_Click”方法体上面添加代码,创建一个dld类实例:

数据挖掘交友

/// <summary> 数据挖掘工具

/// 创建一个 dld 类对象 数据挖掘研究院

/// </summary> 数据挖掘工具

private dld myfun=new dld(); 数据挖掘实验室

  数据挖掘交友

  3. 在“B3_Click”方法体内添加如下代码: 数据挖掘论坛

myfun.LoadDll("Count.dll"); // 加载 "Count.dll" 数据挖掘工具

myfun.LoadFun("_count@4"); // 调入函数 count, "_count@4" 是它的入口,可通过 Depends 查看

 

数据挖掘工具

4. Form1cs[设计]”视图中双击按钮B4,在“B4_Click”方法体内添加如下代码:

数据挖掘工具

object[] Parameters = new object[]{(int)0}; // 实参为 0 数据挖掘论坛

Type[] ParameterTypes = new Type[]{typeof(int)}; // 实参类型为 int 数据挖掘交友

ModePass[] themode=new ModePass[]{ModePass.ByValue}; // 传送方式为值传 数据挖掘交友

Type Type_Return = typeof(int); // 返回类型为 int

数据挖掘实验室

// 弹出提示框,显示调用 myfun.Invoke 方法的结果,即调用 count 函数

数据挖掘工具

MessageBox.Show(" 这是您装载该 Dll 后第 "+myfun.Invoke(Parameters,ParameterTypes,themode,Type_Return).ToString() 数据挖掘实验室

+" 次点击此按钮。 "," 挑战杯 ");

数据挖掘研究院

  数据挖掘论坛


5. Form1cs[设计]”视图中双击按钮B5,在“B5_Click”方法体内添加如下代码: 数据挖掘论坛

myfun.UnLoadDll(); 数据挖掘工具

6. 按“F5”运行该程序,并先点击按钮B3加载“Count.dll,接着点击按钮B4三次以调用3次“count(0)先后弹出的提示框如下

数据挖掘研究院

          这三个提示框所得出的结果说明了静态变量S 经初始化后,再传入实参“0也不会改变其值为“0

数据挖掘论坛

7. 点击按钮B5以卸载“Count.dll”,再点击按钮B3进行装载“Count.dll”,再点击按钮B4查看调用了“count(0)”的结果:

从弹出的提示框所显示的结果可以看到又开始重新计数了,也就是实现了DLL的动态装载与卸载了。 数据挖掘实验室

 

数据挖掘工具

(三)     调用托管DLL一般方法 数据挖掘工具

C# 调用托管DLL是很简单的,只要在“解决方案资源管理器”中的需要调用DLL的项目下用鼠标右击“引用”,并选择“添加引用”,然后选择已列出的DLL或通过浏览来选择DLL文件,最后需要用using 导入相关的命名空间。

(四)     动态调用托管DLL

数据挖掘工具

C# 动态调用托管DLL也需要借助System.Reflection.Assembly里的类和方法,主要使用了Assembly.LoadFrom。现在,用例子说明: 数据挖掘工具

     首先,启动VS.NET,新建一个Visual C# 项目,使用的模板为“类库”,名称为“CsCount”,并在类“Class1添加静态整型变量S及方法count

数据挖掘交友

// 由于 static 不能修饰方法体内的变量,所以需放在这里,且初始化值为 int.MinValue

数据挖掘交友

static int S=int.MinValue; 数据挖掘研究院

public int count(int init)

{// 判断 S 是否等于 int.MinValue ,是的话把 init 赋值给 S 数据挖掘实验室

if(S==int.MinValue) S=init; 数据挖掘研究院

S++; //S 自增 1 数据挖掘交友

return S; // 返回 S

数据挖掘交友

}

  数据挖掘研究院

然后,打开项目“Tzb”,向“Form1窗体中添加一个按钮,Name属性为“B6Text属性为“用Assembly类来动态调用托管DLL”,调整到适当大小和位置,双击按钮B6,转入代码视图,先导入命名空间:using System.Reflection; 接着添加Invoke方法和B6_Click方法代码:

private object Invoke(string lpFileName,string Namespace,string ClassName,string lpProcName,object[] ObjArray_Parameter) 数据挖掘交友

{

数据挖掘交友

Try { // 载入程序集

Assembly MyAssembly=Assembly.LoadFrom(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)

数据挖掘研究院

{ 数据挖掘实验室

object o=Activator.CreateInstance(t); 数据挖掘交友

return m.Invoke(o,ObjArray_Parameter);

} 数据挖掘实验室

else MessageBox.Show(" 装载出错 !"); 数据挖掘研究院

} 数据挖掘交友

}

数据挖掘研究院

}//try

catch(System.NullReferenceException e)

数据挖掘交友

{ 数据挖掘工具

MessageBox.Show(e.Message); 数据挖掘实验室

}//catch

return (object)0;

数据挖掘实验室

}// Invoke

数据挖掘研究院

  数据挖掘论坛

B6_Click”方法体内代码如下:

数据挖掘研究院

// 显示 count(0) 返回的值 数据挖掘交友

MessageBox.Show(" 这是您第 "+Invoke("CsCount.dll","CsCount","Class1","count",new object[]{(int)0}).ToString()+" 次点击此按钮。 "," 挑战杯 "); 数据挖掘交友

  数据挖掘论坛

最后,把项目“CsCount”的binDebug文件夹中的CsCount.dll复制到项目“Tzb”的binDebug文件夹中,按“F5运行该程序,并点击按钮B6三次,将会弹出3个提示框,内容分别是“这是您第 1次点击此按钮。”、“这是您第 2次点击此按钮。”、“这是您第 3次点击此按钮。”,由此知道了静态变量S在这里的作用。

  数据挖掘实验室

() C#程序嵌入DLL的调用 数据挖掘研究院

     DLL文件作为资源嵌入在C#程序中,我们只要读取该资源文件并以“byte[]”返回,然后就用“Assembly Load(byte[]);”得到DLL中的程序集,最后就可以像上面的Invoke方法那样对DLL中的方法进行调用。当然不用上面方法也可以,如用接口实现动态调用,但DLL中必须有该接口的定义并且程序中也要有该接口的定义;也可用反射发送实现动态调用[4]。现在我只对像上面的Invoke方法那样对DLL中的方法进行调用进行讨论,为了以后使用方便及实现代码的复用,我们可以结合上一个编写一个类。

数据挖掘论坛

1)        ldfs类的编写:

在项目“Tzb”中新建一个名为ldfs的类,意为“load dll from resource”,请注意,在这个类中“resource”不只是嵌入在EXE程序中的资源,它也可以是硬盘上任意一个DLL文件,这是因为ldfs的类中的方法LoadDll有些特别,就是先从程序的内嵌的资源中查找需加载的DLL,如果找不到,就查找硬盘上的。 数据挖掘论坛

首先导入所需的命名空间:

数据挖掘实验室

using System.IO; // 对文件的读写需要用到此命名空间

using System.Reflection; // 使用 Assembly 类需用此命名空间

数据挖掘工具

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

声明一静态变量MyAssembly

// 记录要导入的程序集

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

{// 如果资源没有所需的 DLL ,就查看硬盘上有没有,有的话就读取

数据挖掘研究院

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方法来卸载DLL 数据挖掘实验室

public void UnLoadDll()

{// 使 MyAssembly 指空 数据挖掘实验室

MyAssembly=null;

数据挖掘工具

} 数据挖掘工具

添加Invoke方法来进行对DLL中方法的调用,其原理大体上和“Form1cs”中的方法Invoke相同,不过这里用的是Assembly.Load”,而且用了静态变量MyAssembly来保存已加载的DLL,如果已加载的话就不再加载,如果还没加载或者已加载的不同现在要加载的DLL就进行加载,其代码如下所示:

数据挖掘论坛

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

{

数据挖掘交友

try 数据挖掘论坛

{// 判断 MyAssembly 是否为空或 MyAssembly 的命名空间不等于要调用方法的命名空间,如果条件为真,就用 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) 数据挖掘论坛

{// 调用并返回

数据挖掘论坛

object o=Activator.CreateInstance(t); 数据挖掘论坛

return m.Invoke(o,ObjArray_Parameter); 数据挖掘交友

}

else 数据挖掘研究院

System.Windows.Forms.MessageBox.Show(" 装载出错 !"); 数据挖掘实验室

}

数据挖掘研究院

}

}

catch(System.NullReferenceException e) 数据挖掘研究院

{ 数据挖掘工具

System.Windows.Forms.MessageBox.Show(e.Message); 数据挖掘交友

} 数据挖掘实验室

return (object)0;

} 数据挖掘研究院

 

数据挖掘交友

 

2)        ldfs类的使用: 数据挖掘实验室

1. CsCount.dll作为“嵌入的资源”添加到项目“Tzb”中。

2. 向“Form1”窗体中添加两个按钮,NameText属性分别为“B7”、“ldfs.Invoke调用count”;“B8”、“UnLoadDll”,并将它们调整到适当大小和位置。

数据挖掘论坛

3. 打开“Form1cs”代码视图,添加一个ldfs实例:

数据挖掘交友

// 添加一个 ldfs 实例 tmp 数据挖掘工具

private ldfs tmp=new ldfs();

4. 在“Form1cs[设计]”视图中双击按钮B7,在“B1_Click”方法体内添加如下代码: 数据挖掘工具

// 调用 count(0), 并使用期提示框显示其返回值 数据挖掘交友

MessageBox.Show(" 这是您第 "+tmp.Invoke("CsCount.dll","CsCount","Class1","count",new object[]{(int)0}).ToString()+" 次点击此按钮。 "," 挑战杯 "); 数据挖掘交友

5. 在“Form1cs[设计]”视图中双击按钮B7,在“B1_Click”方法体内添加如下代码:

// 卸载 DLL

数据挖掘实验室

tmp.UnLoadDll(); 数据挖掘工具

6. F5”运行该程序,并先点击按钮B7三次,接着点击按钮B8,最后再点击按钮B7,此时发现又开始重新计数了,情况和“dld类的使用”类似,也就是也实现了DLL的动态装载与卸载了 数据挖掘实验室

    说明:以上所用到的所有源代码详见附件1:Form1.cs、附件2:dld.cs、附件3:ldfs.cs、附件4:Count.cpp、附件5:Class1.cs

数据挖掘研究院

 

三、        数据挖掘研究院

使用DLL有很多优点,如:节省内存和减少交换操作;开发大型程序时可以把某些模块分配给程序员,程序员可以用任何一门他所熟悉的语言把该模块编译成DLL文件,这样可以提高代码的复用,大大减轻程序员的工作量。当然DLL也有一些不足,如在提要中提及的问题。所以,如何灵活地调用DLL应该是每位程序员所熟知的。 数据挖掘工具

C# 语言有很多优点,越来越多的人开始使用它来编程。但是,C#还有一些不足,如对不少的底层操作是无能为力的,只能通过调用Win32 DLL C++等编写的DLL;另外,一般认为C#程序的保密性不够强,因为它容易被Reflector 反编译而得到部分源码,所以需要使用混合编程加强C#程序的保密性,而把DLL嵌入C#程序并实现动态调用的方法是比较理想的方法,因为可以把DLL文件先用某一算法进行加密甚至压缩后再作为资源文件添加到C#程序中,在程序运行时才用某一算法进行解压解密后才进行加载,所以即使用反编译软件,也只能得到一个资源文件,且这个资源文件是用一个复杂算法进行加密过的,不可能再次对资源文件中的内容进行反编译,从而大大加强了代码的保密性。 数据挖掘实验室

  数据挖掘实验室

 

数据挖掘实验室

参考文献:

[1]  引自:《什么是 DLL?》,网址: http://support.microsoft.com/default.aspx?scid=kb;zh-cn;815065 数据挖掘研究院

[2] 《在 C# 中通过 P/Invoke 调用Win32 DLL Jason Clark

网址:http://www.microsoft.com/china/msdn/library/langtool/vcsharp/ousNET.mspx 数据挖掘研究院

[3] 《深入分析WindowsLinux动态库应用异同》刘世栋 杨林,

数据挖掘实验室

网址:http://tech.ccidnet.com/art/302/20050919/336005_1.html

数据挖掘工具

[4] C# 程序设计》 Jesse Liberty  刘基诚 ,中国电力出版社

数据挖掘论坛

[数据挖掘专家] [数据挖掘研究院] [数据挖掘论坛] [数据挖掘实验室]
上一篇:C#程序实现动态调用DLL的研究
下一篇:C#程序实现动态调用DLL的研究
最新评论共有 0 位网友发表了评论 , 查看所有评论
发表评论( 不能超过250字,需审核,请自觉遵守互联网相关政策法规。 )
匿名?
数据挖掘网站导航 数据挖掘论坛导航
  • 数据挖掘工具
  • 数据挖掘论坛
  • DataCruncher - Cognos
  • MineSet - MathSoft
  • Intelligent Miner - GainSmarts
  • Sqlserver - SAS - Clementine
  • CART - Weka - WizSoft
  • NeuroShell - ModelQuest
  • data mining tools - Darwin
  • 数据挖掘交友
  • 数据挖掘博客
  • 数据挖掘工具
  • 数据挖掘资源
  • 数据挖掘技术算法
  • 数据挖掘相关期刊、会议
  • 研究院联盟合作专区
  • 数据挖掘基础与相关技术
  • 数据挖掘厂商与就业
  • 数据挖掘研究者乐园
  • 知名厂商数据挖掘工具资料
  • 国内数据挖掘实验室
  • Foreign Data Mining Lab
  • 热点关注
  • 挑战C#学习的最快速度
  • C#模仿QQ截图功能
  • C# 关于开机自动运行程序方式之一
  • 第一章 C#简介
  • 利用C#实现分布式数据库查询
  • Visual Studio 2005 Hands-On Tutorial - P
  • C#入门代码
  • .NET架构与模式探索
  • 用C#代码编写的SN快速输入工具
  • C# 关于开机自动运行程序方式之一
  • 论坛最新话题
  • Foundations of Statistical Natural Langu
  • Game Theory meet Data Mining: A Recent P
  • System Building: How does it help or hin
  • 数据挖掘与Clementine培训
  • 新手报到
  • 求 SASEM 客户流失预测分析
  • 数据挖掘工程师/搜索研究院—北京——无线
  • 数据挖掘入门介绍(如何着手数据挖掘)
  • Information Overload Survey Results
  • The INEX 2005 Workshop on Element Retrie
  • 相关资讯
  • 彻底剖析C# 2.0泛型类的创建和使用
  • 对C# 2.0中匿名方法的怀疑分析
  • EasySP管理解决方案基于Microsoft .NET架构
  • .NET架构与模式探索
  • .NET架构的核心开发技术
  • 用C#代码编写的SN快速输入工具
  • C#链接数据库技巧
  • C#设计模式编程之抽象工厂模式新解
  • 第一章 C#简介
  • 第七章 异常处理
  • 数据挖掘实验室资料
  • 数据挖掘博客地址
  • 数据挖掘实验室网站地址
  • Prepare for Medicare audits by using dat
  • 注册成为SAS用户与爱好者俱乐部会员
  • 水南梅
  • 明日烟
  • 新人报道
  • 下载
  • 厦门服务器托管,450元/月—0592-5177319 高
  • 买空间送域名--0592-5177319 高静