C#实现动态调用Windows DLL (转载自中国IT实验室)

本文介绍了一种在C#中动态调用Windows DLL的方法。通过使用P/Invoke机制,可以实现从托管代码到本地Windows DLL的函数调用。文中详细展示了如何加载DLL文件、获取函数指针并构建调用模型。

部分代码来自于网络;废话不多说,上代码:

调用方法:

object obj = WinDllInvoke("Kernel32.dll", "Beep", new object[] { 750, 300 }, typeof(void));
函数代码:

ContractedBlock.gifExpandedBlockStart.gifCode
 1 [System.Runtime.InteropServices.DllImport("kernel32")]
 2          private static extern IntPtr LoadLibrary(string lpLibFileName);
 3  
 4          [System.Runtime.InteropServices.DllImport("kernel32")]
 5          private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
 6  
 7          [System.Runtime.InteropServices.DllImport("kernel32")]
 8          private static extern IntPtr FreeLibrary(IntPtr hLibModule);
 9 
10ExpandedBlockStart.gifContractedBlock.gif        /**//// 
11         /// 动态调用Windows DLL
12         /// 
13         /// Dll文件名
14         /// 待调用的函数名
15         /// 函数参数
16        /// 返回值
17         /// 调用结果

18         private static object WinDllInvoke(string fileName, string funName, object[] objParams, Type returnType)
19ExpandedBlockStart.gifContractedBlock.gif         {
20             IntPtr libHandle = IntPtr.Zero;
21 
22ExpandedSubBlockStart.gifContractedSubBlock.gif             try             {                 //获取函数地址
23                libHandle = LoadLibrary(fileName);
24                if (libHandle == IntPtr.Zero) return null;
25                 IntPtr procAddres = GetProcAddress(libHandle, funName);
26                if (procAddres == IntPtr.Zero) return null;
27                 
28                 //获取参数类型
29                Type[] paramTypes = new Type[objParams.Length];
30                 for (int i = 0; i < objParams.Length; ++i)
31ExpandedSubBlockStart.gifContractedSubBlock.gif                {
32                     paramTypes[i] = objParams[i].GetType();
33                 }

34 
35                //构建调用方法模型
36                 AssemblyName asembyName = new AssemblyName();
37                 asembyName.Name = "WinDllInvoke_Assembly";
38                AssemblyBuilder asembyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asembyName, AssemblyBuilderAccess.Run);
39                 ModuleBuilder moduleBuilder = asembyBuilder.DefineDynamicModule("WinDllInvoke");                 MethodBuilder methodBuilder = moduleBuilder.DefineGlobalMethod("InvokeFun", MethodAttributes.Public | MethodAttributes.Static, returnType, paramTypes);
40
41                //获取一个 ILGenerator ,用于发送所需的 IL 
42                 ILGenerator IL = methodBuilder.GetILGenerator();
43                 for (int j = 0; j < paramTypes.Length; ++j)
44ExpandedSubBlockStart.gifContractedSubBlock.gif                 {
45                     //将参数压入堆栈
46                     if (paramTypes[j].IsValueType)
47ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
48                        IL.Emit(OpCodes.Ldarg, j); //By Value
49                     }

50                     else
51ExpandedSubBlockStart.gifContractedSubBlock.gif                   {
52                         IL.Emit(OpCodes.Ldarga, j); //By Addrsss
53                     }

54                 }

55
56               // 判断处理器类型
57                if (IntPtr.Size == 4)
58ExpandedSubBlockStart.gifContractedSubBlock.gif                 {
59                    IL.Emit(OpCodes.Ldc_I4, procAddres.ToInt32());
60                 }

61                else if (IntPtr.Size == 8)
62ExpandedSubBlockStart.gifContractedSubBlock.gif                {
63                    IL.Emit(OpCodes.Ldc_I8, procAddres.ToInt64());
64                }

65                 else
66ExpandedSubBlockStart.gifContractedSubBlock.gif               {
67                    throw new PlatformNotSupportedException("不好意思,偶不认得你哦!");
68}

69 IL.EmitCalli(OpCodes.Calli,CallingConvention.StdCall, returnType, paramTypes);
70               IL.Emit(OpCodes.Ret); // 返回值 
71               moduleBuilder.CreateGlobalFunctions(); 
72                // 取得方法信息 
73  MethodInfo methodInfo=moduleBuilder.GetMethod("InvokeFun");
74
75                return methodInfo.Invoke(null, objParams);// 调用方法,并返回其值
76             }

77ExpandedSubBlockStart.gifContractedSubBlock.gif             catch return null; }
78             finally
79ExpandedSubBlockStart.gifContractedSubBlock.gif             {
80                 if (libHandle != IntPtr.Zero) FreeLibrary(libHandle); //释放资源
81             }

82         }

83
84

 

转载于:https://www.cnblogs.com/leleroyn/articles/1545321.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值