C# PInvoke(DllImport使用) 进阶教程(一)转
我们曾经熟悉的WindowsAPI, 我们曾经花费了大量精力写的代码,难道我们就要轻易放弃吗 不过当下微软已经把向下兼容性放在很重要的位置.
C#程序员使用已有的代码来作为自己程序的一部分是很普通的事情.所以NET为了解决使用已有代码的问题作了很多方面的工作.比如说对于已有的C++
代码你可以使用C++托管扩展(managed extensions)来进行封装,以及将会着重讲到的P/Invoke。
1) P/Invoke是什么?
P/Invoke的全称是Platform Invoke (平台调用) 它实际上是一种函数调用机制通 过P/Invoke我们就可以调用非托管DLL中的函数
实际上很多NET基类库中定义的类 型内部部调用了从Kernel32.dll,User32.dll,gdi32.dll等非托管DLL中导出的函数。
2) 看一个最简单的例子
//这个只是设置鼠标相对于屏幕位置的系统函数,当然还有许多API函数的位置是需 要公式计算的(例如:SendInput函数,位于user32.dll内)。
[DllImportAttribute("user32.dll", EntryPoint="SetCursorPos")]
[return:MarshalAsAttribute(UnmanagedType.Bool)] //可写可不写,定义如何封送返回参数
public static extern bool SetCursorPos(int X, int Y) ;
3) P/Invoke的过程(引用图)

P/Invoke依次执行以下操作.(理解重要)
1 查找包含该函数的非托管DLL
2 将该非托管DLL加载到内存中
3 查找函数在内存中的地址并将其参数按照函数的调用约定压栈
注意事项:只在第一次调用函数时,才会查找和加载非托管DLL并查找函数在内存中的地址。
4 将控制权转移给非托管函数
注意:当非托管函数产生异常时,P/Invoke会将异常传递给托管调用方。但需要设置相关特性,后面 章节会有相关说明。
1).要使用P/Invoke我们需要描述调用函数的原型.CLR会使用这些信息进行调用.
下面用一个简单的例子来说明如何使用P/Invoke 在这个例子中我们将调用SetCursorPos 这个API函数来做说明。
该函数的定义是这样描述的:

函数功能:该函数把光标移到屏幕的指定位置。如果新位置不在由 ClipCursor函数设置的屏幕矩形区域之内,则系统自动调整坐标,使得光标在矩形之内。 函数原型:BOOL SetCursorPos(int X,int Y); 参数:X:指定光标的新的X坐标,以屏幕坐标表示。Y:指定光标的新的Y坐标,以屏幕坐标表示。 返回值:如果成功,返回非零值;如果失败,返回值是零 备注:该光标是共享资源,仅当该光标在一个窗口的客户区域内时它才能移动该光标。

2).开始使用
为了在C#中正确的表示以上声明.我们需要将Win32类型转换为对应的C#类型.int是四个字节的整数我们可以使用int或者 uint.
在这里两者的区别并不大,我选择使用int.一来int更常用,二来 int是CLS兼容类型(这意味着在所有基于NET都具有这个类型).BOOL对应的则是bool.
好了,我们可以写出SetCursorPos(...)函数的C#版本定义了
public static extern bool SetCursorPos(int X, int Y) ;
这个声明已经告诉了运行时该如何调用SetCursorPos(...)函数.下面就要告诉运行时应该到哪里去找到这个函数了.同样
通过MSDN.我们可以知道SetCursorPos(...)函数被定义在user32.dll 库中.这意味着SetCursorPos(...)函数的运行时代码在user32.dll中.
我们用DIIlmport属性来告诉运行时SetCursorPos()函数的位置
[DIIImport(”user32.dll”)]
好了!一切准备就绪了.下面就让我们来看看移动鼠标位置把。(让鼠标在动一会儿把..)

using System;
using System.Runtime.InteropServices; namespace ConsoleTest
{ class Program
{ [DllImportAttribute("user32.dll", EntryPoint = "SetCursorPos")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool SetCursorPos(int x, int y); //该实例运行效果为 鼠标随机在屏幕内跳动
static void Main(string[] args)
{
Random r = new Random(unchecked((int)DateTime.Now.Ticks));
int i = 1;
do
{
int x = r.Next(0, Screen.PrimaryScreen.Bounds.Width);
int y = r.Next(0, Screen.PrimaryScreen.Bounds.Height);
SetCursorPos(x, y);
i++;
Thread.Sleep(300); } while (i < 100);
Console.ReadKey(); //^_^,如果你写个随机数无限循环,就可以让别人永远无法使用鼠标,除非关 //机。自己试的时候别写死循环,小心关不掉。 }
}
}

需要注意的一点是DIIImport属性允许你可以调用任意的Win32代码.这其中可能会有一些不怀好意的函数.
所以在使用P/Invoke调用非托管代码时需要你完全信任所调用的函数。
C# PInvoke(DllImport使用) 进阶教程(一)转的更多相关文章
- duilib进阶教程 -- 总结 (17)
整个教程的代码下载:http://download.csdn.net/detail/qq316293804/6502207 (由于duilib进阶教程主要介绍界面,所以这个教程只给出界面相关的代码,完 ...
- duilib进阶教程 -- Container控件的bug (14)
在<duilib进阶教程 -- TreeView控件的bug (9)>里,Alberl发现了两个bug,并解决了其中一个,现在教程已经接近尾声啦,所以Alberl就解决了另外一个bug. ...
- Gensim进阶教程:训练word2vec与doc2vec模型
本篇博客是Gensim的进阶教程,主要介绍用于词向量建模的word2vec模型和用于长文本向量建模的doc2vec模型在Gensim中的实现. Word2vec Word2vec并不是一个模型--它其 ...
- Bash脚本15分钟进阶教程
转载: Bash脚本15分钟进阶教程 这里的技术技巧最初是来自谷歌的"Testing on the Toilet" (TOTT).这里是一个修订和扩增版本. 脚本安全 我的所有ba ...
- Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!
分类: Android高手进阶 Android基础教程 2012-09-14 18:10 29759人阅读 评论(35) 收藏 举报 android相册layoutobjectclassloade ...
- Nodejs爬虫进阶教程之异步并发控制
Nodejs爬虫进阶教程之异步并发控制 之前写了个现在看来很不完美的小爬虫,很多地方没有处理好,比如说在知乎点开一个问题的时候,它的所有回答并不是全部加载好了的,当你拉到回答的尾部时,点击加载更多,回 ...
- Modelbuilder进阶教程
Modelbuilder进阶教程 By 李远祥 Modelbuilder 进阶1 自定义变量 参数是用来交互操作的,因此,参数具备非常大的灵活性,包括参数的定义和调用. 除了工具里面的参数之外,还可以 ...
- SpringBoot进阶教程(二十九)整合Redis 发布订阅
SUBSCRIBE, UNSUBSCRIBE 和 PUBLISH 实现了 发布/订阅消息范例,发送者 (publishers) 不用编程就可以向特定的接受者发送消息 (subscribers). Ra ...
- keil进阶教程
前言 keil只懂得创建软件工程是远远不够的,如果要想顺心使用,应该要懂得部分配置,这样使用心情顺畅,码代码也会越发高效. 设置字号字体 编辑点击编辑菜单,会出现很多子目录,找到配置,点击进入设置页面 ...
随机推荐
- MyEclipse 选中右侧编辑的文件时自动展开左侧目录树
- 7-13IN和NOT IN 子查询
IN后面的子查询可以返回多条记录. SELECT ...FROM WHERE 查询表达式 IN(子查询) 常用IN替换等于(=)的比较子查询. 用法: (1)使用 :IN关键字可以使父查询匹配子查询 ...
- mysql 查询优化规则
.请不要在SELECT中使用DISTINCT: #会用到临时表 .尽可能不要SELECT *,而应该查询需要用到的指定几个字段: .不要对两个大表进行联合,无论是内联或外联.对于需要对两个或多个表进行 ...
- PMP 第十三章 项目干系人管理
1.识别干系人是干什么?早期就识别干系人的原因是什么?识别干系人的输入和工具有哪些?干系人分析的几种模型是哪些?干系人登记册的内容有哪些?bbs.mypm.net 2.干系人参与程度的分类是怎样的?干 ...
- 不通过App Store实现ios应用分发下载安装
最近公司的项目准备着手宣传工作了,宣传手册上要印制App的下载地址二维码,但是客户端应用还未上线,需要一种临时的方案解决应用分发下载问题,通常ios应用必须通过苹果应用商店才能下载安装,但是也可以看到 ...
- CG&CAD resource
Computational Geometry The Geometry Center (UIUC) Computational Geometry Pages (UIUC) Geometry in Ac ...
- 机器学习公开课笔记(5):神经网络(Neural Network)——学习
这一章可能是Andrew Ng讲得最不清楚的一章,为什么这么说呢?这一章主要讲后向传播(Backpropagration, BP)算法,Ng花了一大半的时间在讲如何计算误差项$\delta$,如何计算 ...
- Codeforces Round #229 (Div. 2) C. Inna and Candy Boxes 树状数组s
C. Inna and Candy Boxes Inna loves sweets very much. She has n closed present boxes lines up in a ...
- RPC和Socket,RMI和RPC之间的关系
远程通信机制RPC与RMI的关系 http://blog.csdn.net/zolalad/article/details/25161133 1.RPC RPC(Remote Proced ...
- JDBC操作MySQL数据库案例
JDBC操作MySQL数据库案例 import java.sql.Connection; import java.sql.DriverManager; import java.sql.Prepared ...