当使用一个WIN API函数时,它会检验参数的有效性,然后再设法去执行任务.如果传递了一个无效参数,或者是由于某种原因使程序无法正确执行,那操作系统就会返回一个值,指明该函数在某种程度上运行失败了.WINDOWS中的函数有5种返回值类型.
VOID 表示这种函数执行不可能失败,或者不必关心其失不失败. WINDOWS函数很少是这种类型. 而我们平时写代码中,也应该尽量写有返回值的函数,除非你真的确定它中途不会出意外.
BOOL 如果运行失败它会返回0,如果成功则是非0. 因此,可以通过检测它的返回值是0还是非0来判断一个函数有没有执行成功. 注意,请不要写出这样的代码 if( ret == TRUE). 这样做是很不安全的,因为BOOL不仅只有0和1.它在windef.h中被定义, typedef int BOOL;
HANDLE 如果函数失败,通常返回NULL,否则返回HANDLE值,用于标识你可以操作的一个对象. 但是,某些函数的返回值则是INVALID_HANDLE_VALUE, 它被定义为 -1 . SDK文档在介绍每个函数时都说明了其返回值的含义.用的时候要小心. CreateFile就是这样的一个函数.
LONG/DWORD 这个值比较难以处理,通常这是一种返回数量的函数.如果由于某种原因,函数无法对想要的进行计数,那反该函数通常返回0或-1 (这也是根据相关函数而定). 用的时候要格外小心.
另外,WINDOWS 中定义了一套错误代码列表,用由指明当前API执行后的错误信息. 可以通过GetLastError函数来取得.像这样.
#include <Windows.h> #include <stdio.h> int main() { //打开文件 HANDLE hFile = CreateFile("file.txt",0,0,NULL,OPEN_EXISTING,0,NULL); DWORD er= GetLastError(); return 0; }
返回值 er中便存放了CreateFile调用后,系统记录的错误代码. 并且可们可以看到,hFile的值为INVALID_HANDLE_VALUE。
注意:并不是每个API函数的调用都会更改这个错误代码.某些函数在执行成功时就不会修改. 这个要特别注意.
我们可以通过在VC环境下的"监视"窗口中输入 @err,hr 回车后右边的信息窗口中便会显示出当前错误代码对应的信息提示信息.
像上面这个列子,我们将断点设置在 return 0;这一行上,当执行到此后,我们按上面的方法去做. 你会发现监视窗口中会出现如下提示
@err,hr 0x00000002 系统找不到指定的文件。
当然,我们也可以通过错误代码输出格式化字符串,下面的函数可以做到这一点.
DWORD FormatMessage(
DWORD dwFlags,
LPVOID pSource,
DWORD dwMessageId,
DWROD dwLanguageId,
PTSTR pszBuffer,
DWORD nSize;
va_list *Arguments);
这个函数的功能非常强大,可以在多种语言中进行操作.
#include <Windows.h> #include <stdio.h> int main() { //打开文件 HANDLE hFile = CreateFile("file.txt",0,0,NULL,OPEN_EXISTING,0,NULL); DWORD er= GetLastError(); HLOCAL local; CHAR* buffer[256]; // FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL, // er,MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),(PTSTR)&local,0,NULL); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL, er,MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),(PTSTR)&local,0,NULL); printf("%s",(PCTSTR)LocalLock(local)); getchar(); return 0; }
被注释的部分是用英语输出,而刚刚都说了,这个东西支持多国语言,于是下面就淙了支持中文的做法。 需要说明的是,这个函数的功能非常多。 刚刚仅是演示了从系统和本地BUFFER中取得错误信息。
#define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100
#define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200
#define FORMAT_MESSAGE_FROM_STRING 0x00000400
#define FORMAT_MESSAGE_FROM_HMODULE 0x00000800
#define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000
#define FORMAT_MESSAGE_ARGUMENT_ARRAY 0x00002000
#define FORMAT_MESSAGE_MAX_WIDTH_MASK 0x000000FF
从它强大的定义可以看出来,支持的东西挺多的。 比如下面的组合:
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM 则可 以用于网络相关的错误。。
同样的,用户也可以自己定义错误代码。 错误代码是一个32位的值。
31-30 位,标志错误的严重性。 0 = 成功 1 = 供参考 2 = 警告 3 = 错误
29 位,则标志着错误提供者, 0 表示由MS自己提供, 1 表示由用户提供。所以,用户自定的代码,其29位必需为1。
28 位,保留,必须为0。
27-16 位, 由MS公司定义,标志设备代码。
15-0 位,则是异常代码,MS和客户均要使用此位。
作者:麒麟子