FormatMessage与GetLastError配合使用,排查windows api调用过程中的错误
前一段时间在学习windows api调用过程中,遇到过一些调用错误或者程序没能显示预期的结果,或者直接出现vc运行时错误。
这对新手来说是司空见惯的事,因为不太熟悉难免会出错,出错的信息如果能显示很好的关键字到网上搜索一下倒是很好的,例如
返回错误代码:2。你可以使用Visual studio套件里面的Error Lookup查询一下系统消息列表中的请求消息(system message-ta
ble resource(s) for the requested message):便可得知“系统找不到指定的文件”。有的错误根本就不显示什么错误信息,
这可难倒新手了,我也有一些c程序因此没能完成放置那里窖藏了,不懂什么时候才能碰到他。
偶然间看到网上文章讲解C#中使用托管代码来排查windows api调用,让我想起了以前下载的一段代码,也有类似的函数,于是用
工具搜索到了这段代码,本文的代码片段来自于Expat 2.1.0的win32filemap.c文件
static void
win32perror(const TCHAR *s)
{
LPVOID buf;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &buf,
,
NULL)) {
_ftprintf(stderr, _T("%s: %s"), s, buf);
fflush(stderr);
LocalFree(buf);
}
else
_ftprintf(stderr, _T("%s: unknown Windows error\n"), s);
}
在此基础上稍稍修改了一下写了一个测试代码,如下:
以下在windows xp sp3,visual c++ 6编译通过
#include <windows.h>
#include <stdio.h>
#include <tchar.h> #define STRICT 1
#define WIN32_LEAN_AND_MEAN 1
#ifndef UNICODE
#define UNICODE
#endif static void
win32perror(const TCHAR *s)
{
LPVOID buf;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &buf,
,
NULL)) {
_ftprintf(stderr, _T("%s: %s"), s, buf);
fflush(stderr);
LocalFree(buf);
}
else
_ftprintf(stderr, _T("%s: unknown Windows error\n"), s);
} void main(void)
{
DWORD dwLastError;
const TCHAR *wSZError = {"错误信息\0"};
GetFileAttributes("FileNotexist.txt");
dwLastError = GetLastError(); printf("操作系统返回的错误代码:%d\n",dwLastError);
win32perror(wSZError); }
程序运行结果:
以下是网络上的C#代码处理GetLastError错误代码,版权归原作者所有。
using System;
using System.ComponentModel;
// 使用平台调用技术进行互操作性之前,首先需要添加这个命名空间
using System.Runtime.InteropServices; namespace FormatMessageDotNet
{
class Program
{
// Win32 API
// DWORD WINAPI GetFileAttributes(
// _In_ LPCTSTR lpFileName
//); // 在托管代码中对非托管函数进行声明
[DllImport("Kernel32.dll",SetLastError=true,CharSet=CharSet.Unicode)]
public static extern uint GetFileAttributes(string filename); static void Main(string[] args)
{
// 试图获得一个不存在文件的属性
// 此时调用Win32函数会发生错误
GetFileAttributes("FileNotexist.txt"); // 在应用程序的Bin目录下存在一个test.txt文件,此时调用会成功
//GetFileAttributes("test.txt"); // 获得最后一次获得的错误
int lastErrorCode = Marshal.GetLastWin32Error(); // 将Win32的错误码转换为托管异常
//Win32Exception win32exception = new Win32Exception();
Win32Exception win32exception = new Win32Exception(lastErrorCode);
if (lastErrorCode != )
{
Console.WriteLine("调用Win32函数发生错误,错误信息为 : {0}", win32exception.Message);
}
else
{
Console.WriteLine("调用Win32函数成功,返回的信息为: {0}", win32exception.Message);
} Console.Read();
}
}
}
附:据说使用FormatMessage会有潜在的问题,所以以上代码绕开了这个函数。
FormatMessage函数原型:
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
);
其中第一个参数dwFlags开关如果用到以下参数的确会有潜在的问题。
FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100
Windows Server 2003 and Windows XP:
If the length of the formatted message exceeds 128K bytes, then FormatMessage will not automatically fail with an error of ERROR_MORE_DATA.
也就是消息格式化超过128字节了就会出现问题,并且不会自动报告 ERROR_MORE_DATA错误,以后会单独写一篇FormatMessage函数的详细用法
FormatMessage与GetLastError配合使用,排查windows api调用过程中的错误的更多相关文章
- 浅议Delphi中的Windows API调用(举的两个例子分别是String和API,都不错,挺具有代表性)
浅议Delphi中的Windows API调用http://tech.163.com/school • 2005-08-15 10:57:41 • 来源: 天极网为了能在Windows下快速开发应用程 ...
- Windows API 调用示例
Ø 简介 本文主要记录 Windows API 的调用示例,因为这项技术并不常用,属于 C# 中比较孤僻或接触底层的技术,并不常用.但是有时候也可以借助他完成一些 C# 本身不能完成的功能,例如:通 ...
- 安装Windows 8.1过程中出现的各种问题(无损从MBR转GPT磁盘、不能定位已有分区)
这个周末就安装了个系统,本以为一个小时就能搞定,没想到花费了将近一天. 我的机子是6G内存.500G硬盘,原装系统是Windows 7,现在想换成Windows 8.1,于是下载了64位的Window ...
- Windows API调用外部程序
要在应用程序中启动其他的应用程序,有3个函数可以使用,下面我一一说说他们(我以打开D:\Program Files\zeecalls\目录下的zeecalls.exe应用程序为例): 1.Winexe ...
- 在编译向该请求提供服务所需资源的过程中出现错误。请检查下列特定错误详细信息并适当地修改源代码。 编译器错误消息: CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\41c191fd\ff9345c5\App_Web_login.cshtml.65793277
本地开发环境没问题,但是发布到服务器出现问题或则直接在IIS上修改东西就给我抛出以下错误: 未能写入输出文件"c:\Windows\Microsoft.NET\Framework64 \v4 ...
- 本人arcgis api for javascript中常见错误总结
1. 2.对象不支持"replace"属性或方法 解决办法:一般在ie中执行js会报这样的错误,基本问题就是你引用了某个对象中不存在的方法,可能是这个方法本来存在而你写错了,或者调 ...
- 【SQL】关于存储过程调用过程中事务的点点滴滴
1.调用两个存储过程 ---------------------------------------------------------------- -- 表[dbo].[aaa_test]中[id ...
- Windows 10 安装过程中,在自定义登录页面进入审核模式
按ctrl-f3进入审核模式 https://msdn.microsoft.com/zh-cn/windows/hardware/commercialize/manufacture/desktop/b ...
- 百度地图API在vue-cli中路径错误的问题
在使用百度地图的时候,需要使用自定义的icon图片,百度的案例中使用的是线上地址,但当替换为本地图片路径的时候,错误出现了 这是本地图片地址 ) // 设置覆盖物大小 ); 这里有一点需要注意,这里路 ...
随机推荐
- Windows 10下通过蓝牙连接iPhone个人热点进行共享上网
出处:qiuyi21.cnblogs.com 1.iPhone开启个人热点 在iPhone中打开蓝牙,然后进入“个人热点”并打开开关,如果提示热点发射方式请选择蓝牙那项,然后停留在“个人热点”界面并且 ...
- 【原创】安装LoadRunner12.53 版本时出现Critical error的解决方法
步骤: 1.在官网上下载LoadRunner12.53正版,只不过要注册,然后官网会给个序列号. 2.安装成功之后,快捷键已创建,打开Virtual User Generator时,提示如下错误: 此 ...
- CSS VS JS动画,哪个更快[译]
英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js ...
- 关于Delphi中多线程传递参数的简单问题
http://bbs.csdn.net/topics/390513469/ unit uThread; interface uses Classes; type Th = class(TThread) ...
- Python学习一(面向对象和函数式编程)
学习了一周的Python,虽然一本书还没看完但是也收获颇多,作为一个老码农竟然想起了曾经荒废好久的园子,写点东西当做是学习笔记吧 对Python的语法看的七七八八了,比较让我关注的还是他编程的思想,那 ...
- A quick introduction to HTML
w3c reference : https://www.w3.org/TR/2014/REC-html5-20141028/introduction.html#writing-secure-appli ...
- jquery 高度的获取
alert($(window).height()); //浏览器当前窗口可视区域高度 alert($(document).height()); //浏览器当前窗口文档的高度 alert($(docum ...
- Linux Shell ---系统命令(1)
date命令 功能说明:显示或设置系统时间与日期. 语 法: date [-d <字符串>][-u][+%H%I%K%l%M%P%r%s%S%T%X%Z%a%A%b%B%c%d%D%j%m ...
- jquery实现章节目录效果
<html><head><title>jquery实现章节目录效果</title> <script type="text/javascr ...
- JavaScript编程总结
1. JS加载放在底部 2. JS和CSS合并,一个页面加载的JS和CSS越少越好 3. 尽量使用变量,页非全局变量. 4. 脚本和DOM交互越少越好,尽量批量修改. 5. 批量修 ...