P/Invoke之路2--c#调用 WindowsAPI

C#调用WindowsAPI

1.一个简单示例
2.数据类型对应关系
3.数据封送处理规则
4.DllImportAttribute说明
5.MarshalAsAttribute说明
6.UnmanagedType枚举说明

 

1.一个简单示例

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);
}
}

2.c#托管数据类型与非托管API类型对应表:

API与C#的数据类型对应关系表
API数据类型类型描述C#类型API数据类型类型描述C#类型
WORD16位无符号整数ushortCHAR字符char
LONG32位无符号整数intDWORDLONG64位长整数long
DWORD32位无符号整数uintHDC设备描述表句柄int
HANDLE句柄,32位整数intHGDIOBJGDI对象句柄int
UINT32位无符号整数uintHINSTANCE实例句柄int
BOOL32位布尔型整数boolHWM窗口句柄int
LPSTR指向字符的32位指针stringHPARAM32位消息参数int
LPCSTR指向常字符的32位指针StringLPARAM32位消息参数int
BYTE字节byteWPARAM32位消息参数int
LPDWORD指向32位无符号的整数指针out uintPVOID 或 LPVOID不确定类型指针IntPtr

 

 

 

 

 

 

 

 

 

 

 

3.数据封送:

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;

4.函数调用-DllImportAttribute:

#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; }
    }
}

5.数据封送-MarshalAsAttribute:

#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; }
    }
}

6. 指定如何将参数或字段封送到非托管代码

#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,
    }
}

 

转载于:https://www.cnblogs.com/meixiaoqiang/p/3433260.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值