其中要使用两个未公开的Win32 API函数来存取控制台窗口,这就需要使用动态调用的方法,动态调用中使用的Windows API函数主要有三个,即:Loadlibrary,GetProcAddress和Freelibrary。步骤如下:
1. Loadlibrary: 装载指定DLL动态库
2. GetProcAddress:获得函数的入口地址
3. Freelibrary: 从内存中卸载动态库
但是C#中是没有函数指针,无法直接使用GetProcAddress返回的入口地址。后来找到资料,其实.NET 2.0新增了Marshal.GetDelegateForFunctionPointer 方法可以满足这个要求,MSDN里的解释是:将非托管函数指针转换为委托。
后面的事就简单啦,我把它编成了一个类来方便调用。
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices;namespace feiyun0112.cnblogs.com {public class DllInvoke{Win API#region Win API[DllImport("kernel32.dll")]private extern static IntPtr LoadLibrary(string path);[DllImport("kernel32.dll")]private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);[DllImport("kernel32.dll")]private extern static bool FreeLibrary(IntPtr lib);#endregionprivate IntPtr hLib; public DllInvoke(String DLLPath){hLib = LoadLibrary(DLLPath);}~DllInvoke(){FreeLibrary(hLib); }//将要执行的函数转换为委托public Delegate Invoke (string APIName,Type t) {IntPtr api = GetProcAddress(hLib, APIName);return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);}} }
下面是使用代码
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using feiyun0112.cnblogs.com;namespace ConsoleApplication1 {class Program{public delegate string Test(string a);static void Main(string[] args){DllInvoke dll = new DllInvoke("test2.dll");Test test = (Test)dll.Invoke("testC", typeof(Test));string s = test("ss");Console.WriteLine(s);Console.WriteLine("****************************************");Console.ReadLine();}} }
DllImport会按照顺序自动去寻找的地方:
1、exe所在目录
2、System32目录
3、环境变量目录
所以只需要你把引用的DLL 拷贝到这三个目录下 就可以不用写路径了