没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
使用
使用使用
使用 C#
C#C#
C#调用
调用调用
调用 windows
windowswindows
windows API
APIAPI
API 入门
入门入门
入门(
((
(一
一一
一)
))
)
一
一一
一:
::
:入门
入门入门
入门,
,,
,直接从
直接从直接从
直接从
C#
调用
调用调用
调用
DLL
导出
导出导出
导出
其实我们的议题应该叫做
C#
如何直接调用非托管代码,通常有
2
种方法:
1
. 直接调用从
DLL
导出的函数。
2
. 调用
COM
对象上的接口方法
我主要讨论从
dll
中导出函数,基本步骤如下:
1
.使用
C#
关键字
static
和
extern
声明方法。
2
.将
DllImport
属性附加到该方法。
DllImport
属性允许您指定包含该方法的
DLL
的名
称。
3
.如果需要,为方法的参数和返回值指定自定义封送处理信息,这将重写
.NET Framework
的
默认封送处理。
好,我们开始
1
.首先我们查询
MSDN
找到
GetShortPathName
的定义
The GetShortPathName function retrieves the short path form of the specified
path.
DWORD GetShortPathName(
LPCTSTR lpszLongPath,
LPTSTR lpszShortPath,
DWORD cchBuffer
);
2
.查找对照表进行数据类型的转换(出处:
http://msdn.microsoft.com/msdnmag/issues/03/07/NET/default.aspx?fig=true
)
))
)
Data
Types
Win32 Types Specification CLR Type
char, INT8, SBYTE,
CHARâ€
8-bit signed
integer
System.SByte
short, short int, INT16,
SHORT
16-bit signed
integer
System.Int16
int, long, long int,
INT32, LONG32,
BOOL†, INT
32-bit signed
integer
System.Int32
__int64, INT64,
LONGLONG
64-bit signed
integer
System.Int64
unsigned char, UINT8,
UCHAR†, BYTE
8-bit unsigned
integer
System.Byte
unsigned short, 16-bit unsigned System.UInt16
Win32 Types Specification CLR Type
UINT16, USHORT,
WORD, ATOM,
WCHAR†, __wchar_t
integer
unsigned, unsigned
int, UINT32,
ULONG32, DWORD32,
ULONG, DWORD, UINT
32-bit unsigned
integer
System.UInt32
unsigned __int64,
UINT64,
DWORDLONG,
ULONGLONG
64-bit unsigned
integer
System.UInt64
float, FLOAT Single-precision
floating point
System.Single
double, long double,
DOUBLE
Double-precision
floating point
System.Double
†In Win32 this type is an integer with a specially assigned
meaning; in contrast, the CLR provides a specific type
devoted to this meaning.
3
.调用
GetShortPathName
这个
API
,简单的写法如下(编译通过的话),
using System;
using System.Runtime.InteropServices;
public class MSSQL_ServerHandler
{
[DllImport("kernel32.dll")]
public static extern int GetShortPathName
(
string path,
StringBuilder shortPath,
int shortPathLength
)
}
而我们之前的例子:
using System;
using System.Runtime.InteropServices;
public class MSSQL_ServerHandler
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetShortPathName
(
[
MarshalAs(UnmanagedType.LPTStr)] string path,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,
int shortPathLength
)
}
对比可知,其中
DllImport
,
static
,
extern
基本上是必须有的,其他
CharSet
,
MarshalAs
(
…
)是可选项,在这里即使没有,程序也是可以调用此
API
了。
说明:
1
.
MSSQL_ServerHandler
.
GetShortPathName
方法用
static
和
extern
修饰符声明
并且具有
DllImport
属性,该属性使用默认名称
GetShortPathName
通知编译器此实现来
自
kernel32.dll
。若要对
C#
方法使用不同的名称(如
getShort
),则必须在
DllImport
属
性中使用
EntryPoint
选项,如下所示:
[DllImport("kernel32.dll", EntryPoint="getShort")]
2
.
..
.使用
MarshalAs(UnmanagedType.LPTStr)
保证了在任何平台上都会得到
LPTStr
,否则
默认的方式会把从
C#
中的字符串作为
BStr
传递。
现在如果是仅含有简单参数和返回值的
WIN32 API
,就都可以利用这种方法进行对照,简单的
改写和调用了。
二
二二
二.
..
.背后的原理
背后的原理背后的原理
背后的原理 ―― 知其所以然
知其所以然知其所以然
知其所以然,
,,
,相关的知识
相关的知识相关的知识
相关的知识
1.
..
.平台调用详原理
平台调用详原理平台调用详原理
平台调用详原理
平台调用依赖于元数据在运行时查找导出的函数并封送其参数。下图显示了这一过程。
对非托管 DLL 函数的“平台调用”调用
当“平台调用”调用非托管函数时,它将依次执行以下操作:
查找包含该函数的 DLL。
将该 DLL 加载到内存中。
查找函数在内存中的地址并将其参数推到堆栈上,以封送所需的数据。
注意
注意注意
注意 只在第一次调用函数时,才会查找和加载 DLL 并查找函数在内存中的地址。
将控制权转移给非托管函数。
平台调用会向托管调用方引发由非托管函数生成的异常。
2
.
..
.关于
关于关于
关于
Attribute
(
((
(属性
属性属性
属性,
,,
,注意蓝色字
注意蓝色字注意蓝色字
注意蓝色字)
))
)
属性可以放置在几乎所有声明中(但特定的属性可能限制它在其上有效的声明类型)。在语法上,
属性的指定方法为:将括在方括号中的属性名置于其适用的实体声明之前。例如,具有
DllImport
属性的类将声明如下:
[DllImport] public class MyDllimportClass { ... }
有关更多信息,请参见
DllImportAttribute 类
。
许多属性都带参数,而这些参数可以是定位(未命名)参数也可以是命名参数。任何定位参数都
必须按特定顺序指定并且不能省略,而命名参数是可选的且可以按任意顺序指定。首先指定定位
参数。例如,这三个属性是等效的:
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
[DllImport("user32.dll")]
第一个参数(
DLL
名称)是定位参数并且总是第一个出现,其他参数为命名参数。在此例中,
两个命名参数都默认为假,因此它们可以省略(有关默认参数值的信息,请参见各个属性的文档)。
在一个声明中可以放置多个属性,可分开放置,也可放在同一组括号中:
bool AMethod([In][Out]ref double x);
bool AMethod([Out][In]ref double x);
bool AMethod([In,Out]ref double x);
某些属性对于给定实体可以指定多次。此类可多次使用的属性的一个示例是
Conditional
:
[Conditional("DEBUG"), Conditional("TEST1")] void TraceMethod() {...}
注意
注意注意
注意 根据约定,所有属性名称都以单词
“Attribute”
结束,以便将它们与
.NET Framework
中的其他项区分。但是,在代码中使用属性时不需要指定属性后缀。例如,
[DllImport]
虽等
效于
[DllImportAttribute]
,但
DllImportAttribute
才是该属性在
.NET Framework
中的实际名称。
3
.
..
.
MarshalAsAttribute
类
类类
类
指示如何在托管代码和非托管代码之间封送数据。可将该属性应用于参数、字段或返回值。
该属性为可选属性,因为每个数据类型都有默认的封送处理行为。
大多数情况下,该属性只是使用
UnmanagedType
枚举标识非托管数据的格式。
例如,默认情况下,公共语言运行库将字符串参数作为
BStr
封送到
COM
方法,但是可以通
过制定
MarshalAs
属性,将字符串作为
LPStr
、
LPWStr
、
LPTStr
或
BStr
封送到非托管代码。
某些
UnmanagedType
枚举成员需要附加信息。
三:进阶,如何处理含有复杂的参数和返回值类型的
API
的调用(
To Be Continue…
)
暴强贴
暴强贴暴强贴
暴强贴:
::
:从
从从
从.NET
.NET.NET
.NET 平台调用
平台调用平台调用
平台调用 Win32
Win32Win32
Win32 API
APIAPI
API
小序
小序小序
小序
Win32 API 可以直接控制 Microsoft Windows 的核心,因为 API
(Application Programming Interface)本来就是微软留给我们直接控制
Windows 的接口。想玩儿吗?呵呵,太难了。
C#使用非常简单,写程序就像打拱猪,Sorry -_-! ,搭积木一样简单。
想玩儿吗?呵呵,没办法直接控制 Windows 的核心。
难道就没有两全其美的办法吗?当然不是!要不微软的产品早就没人买
了。其实从 C#(或者说.NET 平台)调用 Win32 API 还是非常简单滴~~~~
今天偶们大家就一起来研究研究。
一
一一
一. 基础知识
基础知识基础知识
基础知识
Win32 API 是 C 语言(注意,不是 C++语言,尽管 C 语言是 C++语言
的子集)函数集。C#语言与
语言与语言与
语言与 C 语言是完全不同的
语言是完全不同的语言是完全不同的
语言是完全不同的(除了语法上比较像),所以,
要想用 C#语言调用 C 语言的 Win32 API,要费上一番周折。首先我们就要准
备一些基础知识。
1. Win32 API 函数放在哪里?
Win32 API 函数是 Windows 的核心,比如我们看到的窗体、按钮、对
话框什么的,都是依靠 Win32 函数“画”在屏幕上的,由于这些控件(有时也称
组件)都用于用户与 Windows 进行交互,所以控制这些控件的 Win32 API 函
数称为“用户界面”函数(User Interface Win32 API),简称 UI 函数;还有
一些函数,并不用于交互,比如管理当前系统正在运行的进程、硬件系统状态的
监视等等……这些函数只有一套,但是可以被所有的 Windows 程序调用(只要
这个程序的权限足够高),简而言之,API 是为程序所共享的。为了达到所有程
序能共享一套 API 的目的,Windows 采用了“动态链接库”的办法。之所以叫“动
态链接库”,是因为这样的函数库的调用方式是“随用随取”而不是像静态链接库
那样“用不用都要带上”。
这里不太好理解,不要紧,我们举个小例子。我们把 Windows 比做一个
游乐场,而把在游乐场里玩儿的小孩比做一个一个程序。小孩在玩的过程中可能
要喝水。我们有两个办法让小家伙们想喝水的时候就有水喝:1.给每个小家伙配
一个水壶,小家伙们喝了的话就喝自己带的水;2.给游乐场配一个饮水机,谁渴
了谁来喝。显然,第二个方法要好得多,这体现在三个地方。第一
第一第一
第一,带着水壶,
小家伙身体不灵活、玩不爽(影响程序的速度),况且这只是带了一个水壶,要
是再带上饭盒呢?还有轮滑、头盔、创可贴、纱布……AK-47 My God,如果带
全了就赶上美国大兵了。所以游乐园里还是有个公用“仓库”要来的方便,让大家
随用随取(动态链接)。第二
第二第二
第二,小家伙们带了那么多东西,占了游乐场很多地方,
让游乐场拥挤不堪,别的小朋友就进不来了(程序体积大,影响程序和系统的性
能)。第三
第三第三
第三,如果某件物品升级了,比如水壶从一升的改为二升的,那么每个小
家伙就必须 go home 去换新的(重新编译程序,由编译器把新的静态库链接进
程序主体里),而第二种情况里,只要游乐场把自己仓库里的水壶换个型号,那
么所有小家伙就都在同一时间拥有了大容量的水壶。(悟空!我就一会儿不在,
你怎么就乱丢东西?!打到小朋友多不好~~~~~)
悟空已经急了,我就不再叽叽歪歪了……呃……Win32 API 函数是放在
Windows 系统的核心库文件中的,这些库在硬盘里的存储形式是.dll 文件。我
们常用到的 dll 文件是 user32.dll 和 kernel32.dll 两个文件,还有其它一些
dll 文件也非常重要,大家要在实践中多积累经验。
我们知道 Win32 API 函数是放在 dll 文件中了,但新问题又来了——我
剩余112页未读,继续阅读
资源评论
- shl_yc2014-08-20学习中,但没成功
- eagle198712013-12-11太有用了,正在学习当中
lxllb8
- 粉丝: 66
- 资源: 579
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功