• 《windows核心编程》第1章 错误处理


    一、错误信息的获取

    1.1 C库错误信息

    1、获取错误信息

    1. #include
    2. #include
    3. #include
    4. int main()
    5. {
    6. fopen("D:\\ASC", "r");
    7. printf("%s\n", strerror(errno));
    8. getchar();
    9. return 0;
    10. }

    2、设置错误信息

    1. #include
    2. #include
    3. #include
    4. int main()
    5. {
    6. fopen("D:\\ASC", "r");
    7. _set_errno(0);
    8. printf("%s\n", strerror(errno));
    9. getchar();
    10. return 0;
    11. }

    1.2 Windows的API

    1、获取错误编号

    2、设置错误编号

    3、用工具获取错误代码对应的错误信息

    4、错误代码各个位数的意义

    二、FormatMessage函数介绍

    2.1 总体概况

    这是windows的API函数,函数是用来将错误编码转换成错误信息字符串的

    在UNICODE编码下被定义为FormatMessageW,我们常用FormatMessageW

    详细内容可见windowsAPI:FormatMessageW 函数 (winbase.h) - Win32 apps | Microsoft Learn

    1. FormatMessageW(
    2.     _In_     DWORD dwFlags,
    3.     _In_opt_ LPCVOID lpSource,
    4.     _In_     DWORD dwMessageId,
    5.     _In_     DWORD dwLanguageId,
    6.     _When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) != 0, _At_((LPWSTR*)lpBuffer, _Outptr_result_z_))
    7.     _When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) == 0, _Out_writes_z_(nSize))
    8.              LPWSTR lpBuffer,
    9.     _In_     DWORD nSize,
    10.     _In_opt_ va_list *Arguments
    11.     );

    2.2 参数1:dwFlags

    DWORD dwFlags

    标志1:FORMAT_MESSAGE_ALLOCATE_BUFFER

    0x00000100

    有这个标志表示这个函数自动分配内存,我们必须给参数lpBuffer,使用这种方式来传递一个未初始化指针变量,(LPTSTR)&lpBuffer。当这个函数返回的时候,这个指针变量就指向一段内存,这个内存中就存放着我们想要的字符串。如果要释放这段内存,就要使用函数LocalFree(这说明FormatMessage函数使用LocalAlloc函数来分配内存)

    标志2:FORMAT_MESSAGE_ARGUMENT_ARRAY

    0x00002000

    Arguments参数是一个数组,不是va_list这种类型的参数

    标志3:FORMAT_MESSAGE_FROM_HMODULE

    0x00000800

    这个标志说明,这个函数接收一个DLL模块,从DLL模块中查找字符串(因为有的错误号,在windows系统API里面还没定义,所以需要另外加DLL,那个里面有错误号对应的错误信息字符串)

    标志4:FORMAT_MESSAGE_FROM_STRING

    从一个字符串中查找消息字符串

    标志5:FORMAT_MESSAGE_FROM_SYSTEM

    0x00001000

    从系统中,获取消息字符串,不是从某个指定的字符串或者DLL中获取消息字符串

    标志6:FORMAT_MESSAGE_IGNORE_INSERTS

    0x00000200

    这个表示说明参数Arguments是否有用,如果设置了这个标志,那么参数Arguments就被函数忽略

    2.3 参数2:lpScource

    LPCVOID lpSource
     

    从哪里获取消息字符串?如果是从系统获取消息字符串的画,这个参数为NULL

    2.4 参数3:dwMessageId

    DWORD dwMessageId,

    消息索引

    2.5 参数4:dwLanguageId

    DWORD dwLanguageId,

    消息的语言种类

    2.6 参数5:lpBuffer

    LPWSTR lpBuffer

    接受消息的内存块指针

    2.7 参数6:nsize

    DWORD nSize

    接受消息的内存块大小

    2.8 参数7:Arguments

    va_list *Arguments

    消息中有些变量的值

    2.9 返回值

    如果函数成功,返回字符消息的字符数

    如果函数失败,返回0,用GetLastError函数获取错误信息

    三、制作错误编号转错误信息小工具

    3.1 建立项目框架

    3.2 按键处理函数

    把上面的函数改成系统分配内存,改动如下

    3.3 添加DLL库中错误信息

    1. void CMFCApplication1Dlg::OnBnClickedButton1()
    2. {
    3. // TODO: 在此添加控件通知处理程序代码
    4. TCHAR* str = NULL;
    5. this->UpdateData(1);
    6. int count = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
    7. NULL, m_value, NULL, (LPWSTR)&str, 200, NULL);
    8. if (!count)
    9. {
    10. this->SetDlgItemTextW(IDC_STATIC1, str);
    11. LocalFree(str);
    12. }
    13. else
    14. {
    15. HMODULE hmodule = LoadLibrary(TEXT("netmsg.dll"));
    16. if (hmodule)
    17. {
    18. count = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
    19. hmodule, m_value, NULL, (LPWSTR)&str, 0, NULL);
    20. if (count)
    21. {
    22. this->SetDlgItemTextW(IDC_STATIC1, (LPCTSTR)LocalLock(str));
    23. LocalFree(str);
    24. }
    25. FreeLibrary(hmodule);
    26. }
    27. if (!count)
    28. {
    29. this->SetDlgItemTextW(IDC_STATIC1, (LPCTSTR)L"没有找到错误代码信息");
    30. }
    31. }
    32. }

    为了好看,初始化的时候给他加入了这个代码

    四、Windows函数返回值的意义

    VOID:这个函数不可能失败

    BOOL:FALSE失败;TRUE 成功

    HANDLE:失败返回NULL,否则返回非零句柄。如果有特殊说明,则可能为特殊值例如:INVALID_HANDLE_VALUE

    PVOID:返回一个内存地址,失败为NULL

    LONG/DWORD:应该根据SDK说明来确定函数状况。

  • 相关阅读:
    六种常用事务解决方案,你方唱罢,我登场(没有最好只有更好)
    设计模式之适配器模式
    JS小数运算精度丢失的问题
    大数据Apache Druid(七):Druid数据的全量更新
    C,C++网络编程学习指南
    NZ系列工具NZ02:VBA读取PDF使用说明
    ab4d:ab3d:ab2d--ZoomPanel for wpf
    Linux 磁盘空间莫名被吃掉,该怎么查?
    556. 下一个更大元素 III
    关于机器学习SVM中KKT条件的深入理解推导
  • 原文地址:https://blog.csdn.net/HuanBianCheng27/article/details/133955291