上网baidu一下或google一下这个东东就有很多人在问这个问题,最近我也用到了这个,所以就留下来以备往后需要是可以查找。我想通过这个来作为C#调用windows APIs的出发点,在以后的随笔当中介绍一下我现阶段用到的一些APIs或非托管类库。
在调用非托管DLL的APIs前,我们应该好好掌握一下DllImportAttribute,MSDN给出的定义为:可将该属性应用于方法。DllImportAttribute 属性提供对从非托管 DLL 导出的函数进行调用所必需的信息。作为最低要求,必须提供包含入口点的 DLL 的名称。
- 1 using System;
- 2 using System.Runtime.InteropServices;
- 3 public delegate bool CallBack(int hwnd, int lParam);
- 4 public class EnumReportApp {
- 5 [DllImport("user32")]
- 6 public static extern int EnumWindows(CallBack x, int y);
- 7 public static void Main()
- 8 {
- 9 CallBack myCallBack = new CallBack(EnumReportApp.Report);
- 10 EnumWindows(myCallBack, 0);
- 11 }
- 12 public static bool Report(int hwnd, int lParam) {
- 13 Console.Write("窗口句柄为");
- 14 Console.WriteLine(hwnd);
- 15 return true;
- 16 }
- 17 }
从上面的例子中我们可以看出,从Kernel32.dll中引入这个API,其中EntryPoint一看就知道是入口点,也就是DLL中的函数名称。其实只要用过VC++的人都知道,Windows APIs中都提供两个版本,一个是W,一个是A也就是Ansi和Unicode之分,现在一般都采用W,Unicode编程,但是.Net和win32交互的时候,默认是使用CharSet.Ansi来传送。在 DllImportAttribute.ExactSpelling 字段为 true 时(它是 Visual Basic .NET 中的默认值)。
平台调用将只搜索您指定的名称。例如,如果指定 MessageBox,则平台调用将搜索 MessageBox,如果它找不到完全相同的拼写则失败。当 ExactSpelling 字段为 false(它是 C++ 托管扩展和 C# 中的默认值),平台调用将首先搜索未处理的别名 (MessageBox),如果没有找到未处理的别名,则将搜索已处理的名称 (MessageBoxA)。#t#
我们可以通过创建一个代理,它带有两个参数hwnd和lparam,第一个参数是一个窗口句柄,第二个参数由应用程序定义,两个参数均为整形。当这个回调函数返回一个非零值时,标示执行成功,零则暗示失败,这个例子总是返回True值。以便持续枚举。最后创建以代理对象(delegate),并把它作为一个参数传递给EnumWindows 函数,平台会自动地 把代理对象转化成函数能够识别的回调格式。
OK,如果熟悉了以上方方面面,基本上也能够调用APIs了别忘了P/Invoke能够帮上很大的忙,我们可以去wiki网站查询我们所要的API:http://pinvoke.net。还需要说明的是很多例子等都来自MSDN和网上检索得到的!!!