C#调用windowsAPI函数

一 调用格式

C#在调用windowsAPI函数接口的时候有一套专门的调用流程

首先我们在调用API函数的时候必须引用命名空间InteropServices

using System.Runtime.InteropServices;

例如我们想调用windows的kernel32.dll动态库中的接口函数中的AllocConsole()控制台函数接口

下面我们用最简单的调用形式来声明调用此函数接口(空方法,即方法体为空)

[DllImport("kernel32.dll")]

public static extern bool AllocConsole();

下面我们可以用DllImportAttribute特性添加字段进一步说明

1 CallingConvention

指示向非托管实现传递方法参数时所用的CallingConvention值

CallingConvention.Cded:调用方清理堆栈。他使用你能够调用具有varargs的函数

CallingConvention.StdCall:被调用方清理堆栈。他是从托管代码调用非托管函数的默认约定

2 CharSet

控制调用函数的名称版本及指示如何向方法封送String参数

CharSet.Ansi:所有字符串转换成ANSI字符串,同时向DLL EnterPoint的名称中追加字母”A“

CharSet.Unicode:所有字符串参数在传递到非托管实现之前都转换成Unicode字符;向DLL EnterPoint的名称中追加字母"W"

CharSet.Auto:这种转换就与平台有关(例如在windows NT上位unicode,而在windows 98上为Ansi)。

CharSet的默认值为Ansi

3 EnterPoint

指示要调用的DLL入口点的名称或序号

如果你的方法名不想与api函数同名的话,一定要指定此参数

例如我想调用user32.dll中的MessageBox函数但是我想以自己的名字MsgBox名字来命名的话

[DllImport("user32.dll",CharSet="CharSet.Auto",EnterPoint="MessageBox")]

public static extern int MsgBox(IntPtr hWnd,string txt,string caption,int type);

4 ExactSpelling

指示是否应修改非托管DLL中的入口点的名称,与CharSet字段中指定的CharSet值相对应。

如果为true,则当DllImportAttribute.CharSet字段设置为CharSet的Ansi值时,向方法名称中追加字母”A“,当DllImportAttribute.CharSet字段设置为CharSet的unicode值时,同方法名称中追加字母”W“,此字段的默认值为false

5 PreserveSig

指示托管方法签名不应该转换成返回HRESULT,并且可能有一个对应返回值的附加[out,retval]参数的非托管签名

6 SerLastError

指示被调用方法从属性化方法返回值之前调用win32 API SetLastError。

true指示调用方将调用SetLastError,默认为false。运行时封送拆收器调用GetLastError并缓存返回的值,以防其他API调用重写。

二 参数类型转换

C++ C#
DWORD int
WORD Int16
字符串指针类型 string
句柄(handle、hWnd) IntPtr
结构或者类 要先用StructLayout特性限定声明结构或类

1 Explicit

用于控制每个数据成员的精确位置。利用Explicit,每个成员必须使用FieldOffsetAttribute指示此字段在类型中的位置:

[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public
class MySystemTime
{
[FieldOffset(0)]public ushort wYear;

[FieldOffset(2)]public ushort wMonth;
[FieldOffset(4)]public ushort
wDayOfWeek;
[FieldOffset(6)]public ushort wDay;
[FieldOffset(8)]public
ushort wHour;
[FieldOffset(10)]public ushort wMinute;

[FieldOffset(12)]public ushort wSecond;
[FieldOffset(14)]public ushort
wMilliseconds;
}

2 Sequential

用于强制将成员按出现的顺序进行顺序布局

例如针对API中的OSVERSIONINFO结构,在.net中定义类或者结构的例子如下

API原型

* API中定义原结构声明
* OSVERSIONINFOA STRUCT
* dwOSVersionInfoSize DWORD
?
* dwMajorVersion DWORD ?
* dwMinorVersion
DWORD ?
* dwBuildNumber DWORD ?
*
dwPlatformId DWORD ?
* szCSDVersion BYTE 128 dup
(?)
* OSVERSIONINFOA ENDS
*
* OSVERSIONINFO equ
<OSVERSIONINFOA>

在.net中声明如下

[ StructLayout( LayoutKind.Sequential )]
public class OSVersionInfo

{
public int OSVersionInfoSize;
public int majorVersion;
public
int minorVersion;
public int buildNumber;
public int platformId;
[
MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String
versionString;
}

注意:结构作为参数的时候,一般前面要加上ref修饰符,否则会出现错误:对象的引用没有指定对象的实例

原文请访问:http://www.jb51.net/article/46041.htm

时间: 2024-11-05 06:06:43

C#调用windowsAPI函数的相关文章

WindowsAPI函数大全(精心总结)

WindowsAPI函数大全(精心总结)    目录 1. API之网络函数... 1 2. API之消息函数... 1 3. API之文件处理函数... 2 4. API之打印函数... 5 5. API之文本和字体函数... 7 6. API之菜单函数... 8 7. API之位图.图标和光栅运算函数... 9 8. API之绘图函数... 10 9. API之设备场景函数... 12 10. API之硬件与系统函数... 14 11. API之进程和线程函数... 17 12. API之控

C#实现百度地图附近搜索&amp;调用JavaScript函数

前一篇文章"C#调用百度地图API入门&解决BMap未定义问题"讲述了如何通过C#调用百度API显示地图,并且如何解决BMap未定义的问题.这篇文章主要更加详细的介绍百度地图的一些功能,包括附近搜索.城市搜索.路线规划.添加覆盖物等等. 希望文章对你有所帮助!如果文章中有不足之处,还请海涵~ 百度官方文档:http://developer.baidu.com/map/jsmobile.htm 官方DEMO例:http://developer.baidu.com/map/jsde

RTX——第19章 SVC 中断方式调用用户函数(后期补历程)

本章节为大家讲解如何采用 SVC 中断方式调用用户函数. 当用户将 RTX 任务设置为工作在非特权级模式时,任务中是不允许访问特权级寄存器的,这个时候使用 SVC 中断,此问题就迎刃而解了. SVC 功能介绍SVC 用于产生系统函数的调用请求.例如,操作系统通常不让用户程序直接访问硬件,而是通过提供一些系统服务函数,让用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件.因此,当用户程序想要控制特定的硬件时,它就要产生一个 SVC 异常,然后操作系统提供的SVC

QT5.3无法自动调用incomingConnection函数的问题(4.7没有这个问题)

最近将qt4.7的一个工程移到5.3,遇到了几个麻烦事,主要是这个incomingConnection监听后无法自动调用的问题,在4.7上是完全没有问题的,到了5.3就不行,网上也查了下,网友们都是放出问题,然而都没有写出解决. 1.一步解决 我之前是这样写的: void TFTPxServer::incomingConnection(int socketDescriptor) { qDebug() << "incomingConnection..."; TFTPxThre

用户选择,调用相应函数的编写方法

用户选择,调用相应函数的编写方法: 1.先输出Menu菜单,让用户选择. 2.创建一个Menu字典k=序号,v=操作函数 3.调用用户选择的相应序号的函数:menu[option](参数) def account_info(acc_data): print(user_data) def repay(acc_data): pass def withdraw(acc_data): pass def transfer(acc_data): pass def pay_check(acc_data): p

第 13 条:使用立即调用的函数表达式创建局部作用域

第 13 条:使用立即调用的函数表达式创建局部作用域这段程序(Bug 程序)输出什么? function wrapElements(a) { var result = [], i, n; for (i = 0, n = a.length; i < n; i++) { result[i] = function() { return a[i]; }; } return result; } var wrapped = wrapElements([10, 20, 30, 40, 50]); var f

C++面试题1:构造函数和虚构函数中能否调用虚函数?

C++面试题1:构造函数和虚构函数中能否调用虚函数? 构造函数跟虚构函数里面都可以调用虚函数,编译器不会报错. C++ primer中说到最好别用 由于类的构造次序是由基类到派生类,所以在构造函数中调用虚函数,虚函数是不会呈现出多态的 类的析构是从派生类到基类,当调用继承层次中某一层次的类的析构函数时意味着其派生类部分已经析构掉,所以也不会呈现多态 因此如果在基类中声明的纯虚函数并且在基类的析构函数中调用之,编译器会发生错误. class Base { public: Base() { Fuct

C++中构造函数能调用虚函数吗?(答案是语法可以,输出错误),但Java里居然可以

环境:XPSP3 VS2005 今天黑总给应聘者出了一个在C++的构造函数中调用虚函数的问题,具体的题目要比标题复杂,大体情况可以看如下的代码: [cpp] view plain copy class Base { public: Base() { Fuction(); } virtual void Fuction() { cout << "Base::Fuction" << endl; } }; class A : public Base { public:

Effective C++ Item 09-绝不在构造函数和析构函数中调用virtual函数

Item 09-绝不在构造函数和析构函数中调用virtual函数(Never call virtual functions during construction or destruction) Why? 由于base class构造函数的执行更早于derived class构造函数,当base class构造函数执行derived class的成员变量尚未初始化.如果期间调用的virtual函数下降至derived class阶层,要知道derived class的函数几乎必然取用local成