zoukankan      html  css  js  c++  java
  • .net 互操作之p/invoke 数据封送(字符串版本ANSI和UniCode,返回错误码,回调函数,常量)(6)

    处理字符串的函数(ANSI和UniCode版本)



    非托管函数后缀名A表示ANSI,W表示宽字符(Unicode),如GetUserName有GetUserNameA和GetUserNameW

    p/inlvoke设置方式

    1.设置CharSet
    DllImport默认为Ansi

    [DllImport("advapi32.dll", CharSet = CharSet.Ansi)]

    2.设置EntryPoint

    [DllImport("advapi32.dll", EntryPoint = "GetUserNameA")]

    3.自动行为

    当设置CharSet 会自动去寻找后缀名为W和A的函数,设置ExactSpelling为true时,需要保证生命函数与非托管函数名是一致的

    [DllImport("advapi32.dll", EntryPoint = "GetUserNameA", CharSet = CharSet.Auto,ExactSpelling=true)]

    4.自动系统平台设置
    当CharSet 设置为Auto时,会根据系统来寻找函数封送

    [DllImport("advapi32.dll", EntryPoint = "GetUserNameW", CharSet = CharSet.Auto)]

    错误码

    首先要设置SetLastError=true

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]

    两种处理方式

    1.使用Win32 API FormatMessage

    public class FormatErrorCode
     {
         const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
         const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
         const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
     
         //Win32 API
         //DWORD WINAPI FormatMessage(
         //  __in      DWORD dwFlags,
         //  __in_opt  LPCVOID lpSource,
         //  __in      DWORD dwMessageId,
         //  __in      DWORD dwLanguageId,
         //  __out     LPTSTR lpBuffer,
         //  __in      DWORD nSize,
         //  __in_opt  va_list* Arguments
         //);
     
         [DllImport("kernel32.dll")]
         public static extern uint FormatMessage(uint dwFlags, IntPtr lpSource,
             uint dwMessageId, uint dwLanguageId, ref IntPtr lpMsgBuf,
             uint nSize, IntPtr Arguments);
     
         //Win32 API
         //HLOCAL WINAPI LocalFree(
         //  __in  HLOCAL hMem
         //);
     
         [DllImport("kernel32.dll", SetLastError = true)]
         public static extern IntPtr LocalFree(IntPtr hMem);
     
         public static string GetLastErrorMsg()
         {
             
             int lastError = Marshal.GetLastWin32Error();
     
             IntPtr lpMsgBuf = IntPtr.Zero;
     
             uint dwChars = FormatMessage(
                 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
                 | FORMAT_MESSAGE_IGNORE_INSERTS,
                 IntPtr.Zero, (uint)lastError, 0, ref lpMsgBuf, 0, IntPtr.Zero);
     
             if (dwChars == 0)
             {
                 return "";
             }
     
             string errorMsg = Marshal.PtrToStringAnsi(lpMsgBuf);
             // 释放内存
             LocalFree(lpMsgBuf);
     
             return errorMsg;
         }
     }

    测试

    public static void TestErrorMsgByWin32Exception()
     {
     
             GetFileAttributes("FileNotFoundDemo.txt");
     
         // error code获得最后一次获得的错误
    int lastErrorCode = Marshal.GetLastWin32Error(); // 将Win32的错误码转化成一个用户友好的托管异常 Win32Exception win32Exception = new Win32Exception(lastErrorCode); Console.WriteLine("GetFileAttributes last win32 error message: {0}", win32Exception.Message); }


    2.使用托管的Win32Exception

    public static void TestErrorMsgByWin32ExceptionDefault()
     {
         // 试图获得一个不存在的文件的属性
         GetFileAttributes("FileNotFoundDemo.txt");
     
         // 使用Win32的缺省构造函数,使其自动调用Marshal.GetLastWin32Error()来
         // 将Win32的错误码转化成一个用户友好的托管异常
         Win32Exception win32Exception = new Win32Exception();
         Console.WriteLine("GetFileAttributes last win32 error message: {0}", win32Exception.Message);
     }

    明显的第2种简单很多,会自动去调用Marshal.GetLastWin32Error()方法

    处理回调函数

    定义常量

    这个比较麻烦,烦是Win32 API 定义的常量,想使用的话,必须重新定义一遍,所以找到常量的值是关键.可以讲一组功能相近的常量定义成枚举

    [Flags]
     public enum FileAttributeFlags : uint
     {
         //文件属性标志
         FILE_ATTRIBUTE_READONLY = 0x00000001,
         FILE_ATTRIBUTE_HIDDEN = 0x00000002,
         FILE_ATTRIBUTE_SYSTEM = 0x00000004,
         FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
         FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
         FILE_ATTRIBUTE_DEVICE = 0x00000040,
         FILE_ATTRIBUTE_NORMAL = 0x00000080,
         FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
         FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
         FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
         FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
         FILE_ATTRIBUTE_OFFLINE = 0x00001000,
         FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
         FILE_ATTRIBUTE_ENCRYPTED = 0x00004000,
         FILE_ATTRIBUTE_VALID_FLAGS = 0x00007fb7,
         FILE_ATTRIBUTE_VALID_SET_FLAGS = 0x000031a7,
     }
  • 相关阅读:
    爬虫必备—性能相关(异步非阻塞)
    JPA自定义查询@Query分页
    iiview Select 选择框打勾选中的内容label和展示的不一致
    ivew Table 固定列设置后,底部拖拽的横轴被覆盖拉不动
    vue消息提示Message
    LeafLet之气泡框隐藏"x"图标
    vue 之 折线图挤压
    iView之清空选择框
    iview之select选择框选中内容后有空格的问题
    iview组件select之默认展示label,并传空value做方法入参
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1809626.html
Copyright © 2011-2022 走看看