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

news/2025/4/1 3:50:19/

一、错误信息的获取

1.1 C库错误信息

1、获取错误信息

#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{fopen("D:\\ASC", "r");printf("%s\n", strerror(errno));getchar();return 0;
}

2、设置错误信息

#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{fopen("D:\\ASC", "r");_set_errno(0);printf("%s\n", strerror(errno));getchar();return 0;
}

1.2 Windows的API

1、获取错误编号

2、设置错误编号

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

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

二、FormatMessage函数介绍

2.1 总体概况

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

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

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

FormatMessageW(_In_     DWORD dwFlags,_In_opt_ LPCVOID lpSource,_In_     DWORD dwMessageId,_In_     DWORD dwLanguageId,_When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) != 0, _At_((LPWSTR*)lpBuffer, _Outptr_result_z_))_When_((dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) == 0, _Out_writes_z_(nSize))LPWSTR lpBuffer,_In_     DWORD nSize,_In_opt_ va_list *Arguments);

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库中错误信息

void CMFCApplication1Dlg::OnBnClickedButton1()
{// TODO: 在此添加控件通知处理程序代码TCHAR* str = NULL;this->UpdateData(1);int count = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,NULL, m_value, NULL, (LPWSTR)&str, 200, NULL);if (!count){this->SetDlgItemTextW(IDC_STATIC1, str);LocalFree(str);}else{HMODULE hmodule = LoadLibrary(TEXT("netmsg.dll"));if (hmodule){count = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,hmodule, m_value, NULL, (LPWSTR)&str, 0, NULL);if (count){this->SetDlgItemTextW(IDC_STATIC1, (LPCTSTR)LocalLock(str));LocalFree(str);}FreeLibrary(hmodule);}if (!count){this->SetDlgItemTextW(IDC_STATIC1, (LPCTSTR)L"没有找到错误代码信息");}}
}

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

四、Windows函数返回值的意义

VOID:这个函数不可能失败

BOOL:FALSE失败;TRUE 成功

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

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

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


http://www.ppmy.cn/news/1166695.html

相关文章

Java数字处理类--Math类--随机数

1. 生成随机数方法&#xff1a; 1.1 Math.random()方法 1.2 Random类 2. Math.random()方法 2.1 Math.random():产生0~1之间的double型随机数 package MathInfo;public class MathRandom {//定义产生偶数的公式&#xff1a;int num (int) num1 (int) (Math.random() * (num…

Uniapp软件库源码 全新带勋章功能(包含前后端源码)

Uniapp软件库全新带勋章功能&#xff0c;搭建好后台 在前端找到 util 这个文件 把两个js文件上面的填上自己的域名&#xff0c; 电脑需要下载&#xff1a;HBuilderX 登录账号 没有账号就注册账号&#xff0c;然后上传文件&#xff0c;打包选择 “发行” 可以打包app h5等等。…

墨迹天气商业版UTF-8模板,Discuz3.4灰白色风格(带教程)

1.版本支持&#xff1a;Discuzx3.4版本&#xff0c;Discuzx3.3版本&#xff0c;DiscuzX3.2版本。包括网站首页&#xff0c;论坛首页&#xff0c;论坛列表页&#xff0c;论坛内容页&#xff0c;论坛瀑布流,资讯列表页(支持多个)&#xff0c;产品列表页(支持多个)&#xff0c;关于…

Mysql 中的性能调优方法

Mysql 性能调优方法可以从四个方面来说&#xff0c;分别是&#xff1a; 表结构与索引 SQL 语句优化 Mysql 参数优化 硬件及系统配置 这四个方面的优化成本和优化效果是成反比的。 表结构和索引的优化 表结构和索引的优化&#xff0c;主要可以下面这些方面去优化&#xff1a; 分…

关于OpenMesh与OpenGL

文章目录 OpenMesh官网OpenMesh是什么&#xff1f;他能做什么&#xff1f;直接无源码安装测试报错&#xff1a;效果: 学习openmesh学习openmesh的流程如下&#xff1a;第一步&#xff0c;了解openmesh库的基本概念第二步&#xff0c;查看openmesh的官方示例&#xff0c;了解简单…

Ubuntu桌面环境的切换方法

你在找它吗&#xff1f; 国内麒麟、深度等系统虽然界面更炫&#xff0c;但——软件仓库与Ubuntu官方已不兼容。国内系统遇到稳定性问题&#xff0c;还是得拿Ubuntu做参照。今天本来介绍下这款Linux桌面。 为什么在 Ubuntu 上考虑 LXQt&#xff1f; 性能&#xff1a;LXQt设计为…

面试算法29:排序的循环链表

问题 在一个循环链表中节点的值递增排序&#xff0c;请设计一个算法在该循环链表中插入节点&#xff0c;并保证插入节点之后的循环链表仍然是排序的。 分析 首先分析在排序的循环链表中插入节点的规律。当在图4.15&#xff08;a&#xff09;的链表中插入值为4的节点时&…

AC修炼计划(AtCoder Regular Contest 167)

传送门&#xff1a;AtCoder Regular Contest 167 - AtCoder 再次感谢樱雪喵大佬的题解&#xff0c;讲的很详细&#xff0c;Orz。 大佬的博客链接如下&#xff1a;Atcoder Regular Contest 167 - 樱雪喵 - 博客园 (cnblogs.com) 第一题很签到&#xff0c;就省略掉了。 第二题…