C#调用WindowsAPI
1.一个简单示例
2.数据类型对应关系
3.数据封送处理规则
4.DllImportAttribute说明
5.MarshalAsAttribute说明
6.UnmanagedType枚举说明
User32.dll中非托管API之MessageBeep:
BOOL MessageBeep( UINT uType // beep type);
调用:
public class Test { [DllImport("User32.dll")] static extern Boolean MessageBeep(UInt32 beepType); static void Beep() { MessageBeep(0); } }
API与C#的数据类型对应关系表
| |||||
API数据类型 | 类型描述 | C#类型 | API数据类型 | 类型描述 | C#类型 |
WORD | 16位无符号整数 | ushort | CHAR | 字符 | char |
LONG | 32位无符号整数 | int | DWORDLONG | 64位长整数 | long |
DWORD | 32位无符号整数 | uint | HDC | 设备描述表句柄 | int |
HANDLE | 句柄,32位整数 | int | HGDIOBJ | GDI对象句柄 | int |
UINT | 32位无符号整数 | uint | HINSTANCE | 实例句柄 | int |
BOOL | 32位布尔型整数 | bool | HWM | 窗口句柄 | int |
LPSTR | 指向字符的32位指针 | string | HPARAM | 32位消息参数 | int |
LPCSTR | 指向常字符的32位指针 | String | LPARAM | 32位消息参数 | int |
BYTE | 字节 | byte | WPARAM | 32位消息参数 | int |
LPDWORD | 指向32位无符号的整数指针 | out uint | PVOID 或 LPVOID | 不确定类型指针 | IntPtr |
1.值类型指针按out,ref方式封送
2.引用类型指针按类型直接封送
3.不透明指针和句柄按System.IntPtr封送
4.文本只有做输入按System.String,用作输入和输出按System.StringBuilder
5.两种方式可以知道处理字符串时信息的传递方向,第一个也是最可靠的一个方法就是首先理解参数的用途,第二种查找 API 参数类型中的字母“C”。
6.数组封送,
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] Phone;
7.字符串封送
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DevName;
等同于
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] devName;
#region 程序集 mscorlib.dll, v4.0.0.0 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll #endregion using System; using System.Reflection; using System.Security; namespace System.Runtime.InteropServices { // 摘要: // 指示该特性化方法由非托管动态链接库 (DLL) 作为静态入口点公开。 [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ComVisible(true)] public sealed class DllImportAttribute : Attribute { // 摘要: // 将 Unicode 字符转换为 ANSI 字符时,启用或禁用最佳映射行为。 public bool BestFitMapping; // // 摘要: // 指示入口点的调用约定。 public CallingConvention CallingConvention; // // 摘要: // 指示如何向方法封送字符串参数,并控制名称重整。 public CharSet CharSet; // // 摘要: // 指示要调用的 DLL 入口点的名称或序号。 public string EntryPoint; // // 摘要: // 控制 System.Runtime.InteropServices.DllImportAttribute.CharSet 字段是否使公共语言运行时在非托管 // DLL 中搜索入口点名称,而不使用指定的入口点名称。 public bool ExactSpelling; // // 摘要: // 指示是否直接转换具有 HRESULT 或 retval 返回值的非托管方法,或是否自动将 HRESULT 或 retval 返回值转换为异常。 public bool PreserveSig; // // 摘要: // 指示被调用方在从特性化方法返回之前是否调用 SetLastError Win32 API 函数。 public bool SetLastError; // // 摘要: // 启用或禁止在遇到被转换为 ANSI“?”字符的无法映射的 Unicode 字符时引发异常。字符。 public bool ThrowOnUnmappableChar; // 摘要: // 使用包含要导入的方法的 DLL 的名称初始化 System.Runtime.InteropServices.DllImportAttribute // 类的新实例。 // // 参数: // dllName: // 包含非托管方法的 DLL 的名称。如果 DLL 包含在某个程序集中,则可以包含程序集显示名称。 public DllImportAttribute(string dllName); // 摘要: // 获取包含入口点的 DLL 文件的名称。 // // 返回结果: // 包含入口点的 DLL 文件的名称。 public string Value { get; } } }
#region 程序集 mscorlib.dll, v4.0.0.0 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll #endregion using System; using System.Reflection; using System.Security; namespace System.Runtime.InteropServices { // 摘要: // 指示如何在托管代码和非托管代码之间封送数据。 [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] [ComVisible(true)] public sealed class MarshalAsAttribute : Attribute { // 摘要: // 指定非托管 System.Runtime.InteropServices.UnmanagedType.LPArray 或 System.Runtime.InteropServices.UnmanagedType.ByValArray // 的元素类型。 public UnmanagedType ArraySubType; // // 摘要: // 指定 COM 使用的非托管 iid_is 特性的参数索引。 public int IidParameterIndex; // // 摘要: // 向自定义封送拆收器提供附加信息。 public string MarshalCookie; // // 摘要: // 指定自定义封送拆收器的完全限定名。 [ComVisible(true)] public string MarshalType; // // 摘要: // 将 System.Runtime.InteropServices.MarshalAsAttribute.MarshalType 作为类型实现。 [ComVisible(true)] public Type MarshalTypeRef; // // 摘要: // 指示 System.Runtime.InteropServices.UnmanagedType.SafeArray 的元素类型。 public VarEnum SafeArraySubType; // // 摘要: // 指示用户定义的 System.Runtime.InteropServices.UnmanagedType.SafeArray 元素类型。 public Type SafeArrayUserDefinedSubType; // // 摘要: // 指示固定长度数组中的元素数,或要导入的字符串中的字符(不是字节)数。 public int SizeConst; // // 摘要: // 指示从零开始的参数,该参数包含数组元素的计数,与 COM 中的 size_is 类似。 public short SizeParamIndex; // 摘要: // 使用指定的 System.Runtime.InteropServices.UnmanagedType 值初始化 System.Runtime.InteropServices.MarshalAsAttribute // 类的新实例。 // // 参数: // unmanagedType: // 数据将以其形式封送的值。 public MarshalAsAttribute(short unmanagedType); // // 摘要: // 使用指定的 System.Runtime.InteropServices.UnmanagedType 枚举成员初始化 System.Runtime.InteropServices.MarshalAsAttribute // 类的新实例。 // // 参数: // unmanagedType: // 数据将以其形式封送的值。 public MarshalAsAttribute(UnmanagedType unmanagedType); // 摘要: // 获取 System.Runtime.InteropServices.UnmanagedType 值,数据将被作为该值封送。 // // 返回结果: // System.Runtime.InteropServices.UnmanagedType 值,数据将被作为该值封送。 public UnmanagedType Value { get; } } }
#region 程序集 mscorlib.dll, v2.0.0.0 // C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll #endregion using System; namespace System.Runtime.InteropServices { // 摘要: // 指定如何将参数或字段封送到非托管代码。 [Serializable] [ComVisible(true)] public enum UnmanagedType { // 摘要: // 4 字节布尔值(true != 0、false = 0)。这是 Win32 BOOL 类型。 Bool = 2, // // 摘要: // 1 字节有符号整数。可使用此成员将布尔值转换为 1 字节、C 样式的 bool(true = 1、false = 0)。 I1 = 3, // // 摘要: // 1 字节无符号整数。 U1 = 4, // // 摘要: // 2 字节有符号整数。 I2 = 5, // // 摘要: // 2 字节无符号整数。 U2 = 6, // // 摘要: // 4 字节有符号整数。 I4 = 7, // // 摘要: // 4 字节无符号整数。 U4 = 8, // // 摘要: // 8 字节有符号整数。 I8 = 9, // // 摘要: // 8 字节无符号整数。 U8 = 10, // // 摘要: // 4 字节浮点数。 R4 = 11, // // 摘要: // 8 字节浮点数。 R8 = 12, // // 摘要: // 在 System.Decimal 上使用,以将十进制数值作为 COM 货币类型而不是 Decimal 封送。 Currency = 15, // // 摘要: // 长度前缀为双字节的 Unicode 字符串。可以在 System.String 数据类型上使用此成员(它是 COM 中的默认字符串)。 BStr = 19, // // 摘要: // 单字节、空终止的 ANSI 字符串。可在 System.String 或 System.Text.StringBuilder 数据类型上使用此成员。 LPStr = 20, // // 摘要: // 一个 2 字节、空终止的 Unicode 字符串。 LPWStr = 21, // // 摘要: // 与平台相关的字符串:在 Windows 98 上为 ANSI,在 Windows NT 和 Windows XP 上为 Unicode。该值仅对平台调用受支持,而对 // COM Interop 则不受支持,原因是不支持导出 LPTStr 类型的字符串。 LPTStr = 22, // // 摘要: // 用于在结构中出现的内联定长字符数组。与 System.Runtime.InteropServices.UnmanagedType.ByValTStr // 一起使用的字符类型由应用于包含结构的 System.Runtime.InteropServices.StructLayoutAttribute 的 // System.Runtime.InteropServices.CharSet 参数确定。应始终使用 System.Runtime.InteropServices.MarshalAsAttribute.SizeConst // 字段来指示数组的大小。 ByValTStr = 23, // // 摘要: // COMIUnknown 指针。可以在 System.Object 数据类型上使用此成员。 IUnknown = 25, // // 摘要: // 一个 COM IDispatch 指针(在 Microsoft Visual Basic 6.0 中为 Object)。 IDispatch = 26, // // 摘要: // 一个用于封送托管格式化类和值类型的 VARIANT。 Struct = 27, // // 摘要: // COM 接口指针。从类元数据获得接口的 System.Guid。如果将此成员应用于类,则可以使用该成员指定确切的接口类型或默认的接口类型。当应用于 // System.Object 数据类型时,此成员将产生 System.Runtime.InteropServices.UnmanagedType.IUnknown // 行为。 Interface = 28, // // 摘要: // SafeArray 是自我描述的数组,它带有关联数组数据的类型、秩和界限。可将此成员与 System.Runtime.InteropServices.MarshalAsAttribute.SafeArraySubType // 字段一起使用,以重写默认元素类型。 SafeArray = 29, // // 摘要: // 当 System.Runtime.InteropServices.MarshalAsAttribute.Value 设置为 ByValArray // 时,必须设置 System.Runtime.InteropServices.MarshalAsAttribute.SizeConst 以指示数组中的元素数。当需要区分字符串类型时,System.Runtime.InteropServices.MarshalAsAttribute.ArraySubType // 字段可以选择包含数组元素的 System.Runtime.InteropServices.UnmanagedType。此 System.Runtime.InteropServices.UnmanagedType // 只可用于作为结构中的字段的数组。 ByValArray = 30, // // 摘要: // 与平台相关的有符号整数。在 32 位 Windows 上为 4 字节,在 64 位 Windows 上为 8 字节。 SysInt = 31, // // 摘要: // 与平台相关的无符号整数。在 32 位 Windows 上为 4 字节,在 64 位 Windows 上为 8 字节。 SysUInt = 32, // // 摘要: // 允许 Visual Basic 2005 在非托管代码中更改字符串,并将结果在托管代码中反映出来。该值仅对平台调用受支持。 VBByRefStr = 34, // // 摘要: // 长度前缀为单字节的 ANSI 字符串。可以在 System.String 数据类型上使用此成员。 AnsiBStr = 35, // // 摘要: // 一个有长度前缀的与平台相关的 char 字符串。在 Windows 98 上为 ANSI,在 Windows NT 上为 Unicode。很少用到这个类似于 // BSTR 的成员。 TBStr = 36, // // 摘要: // 2 字节、OLE 定义的 VARIANT_BOOL 类型(true = -1、false = 0)。 VariantBool = 37, // // 摘要: // 一个可用作 C 样式函数指针的整数。可将此成员用于 System.Delegate 数据类型或从 System.Delegate 继承的类型。 FunctionPtr = 38, // // 摘要: // 一个动态类型,将在运行时确定对象的类型,并将该对象作为所确定的类型进行封送处理。仅对平台调用方法有效。 AsAny = 40, // // 摘要: // 指向 C 样式数组的第一个元素的指针。当从托管到非托管进行封送处理时,该数组的长度由托管数组的长度确定。当从非托管到托管进行封送处理时,将根据 System.Runtime.InteropServices.MarshalAsAttribute.SizeConst // 和 System.Runtime.InteropServices.MarshalAsAttribute.SizeParamIndex 字段确定该数组的长度,当需要区分字符串类型时,还可以后跟数组中元素的非托管类型。 LPArray = 42, // // 摘要: // 一个指针,它指向用于封送托管格式化类的 C 样式结构。仅对平台调用方法有效。 LPStruct = 43, // // 摘要: // 当与 System.Runtime.InteropServices.MarshalAsAttribute.MarshalType 或 System.Runtime.InteropServices.MarshalAsAttribute.MarshalTypeRef // 一起使用时,指定自定义封送拆收器类。System.Runtime.InteropServices.MarshalAsAttribute.MarshalCookie // 字段可用于将附加信息传递给自定义封送拆收器。可以在任何引用类型上使用此成员。 CustomMarshaler = 44, // // 摘要: // 此与 System.Runtime.InteropServices.UnmanagedType.I4 或 System.Runtime.InteropServices.UnmanagedType.U4 // 关联的本机类型将导致参数作为导出类型库中的 HRESULT 导出。 Error = 45, } }