Win32 API:带有FormatMessage()的GetLastError()打印垃圾

时间:2014-08-13 08:45:35

标签: c++ winapi character-encoding mingw wine

我只是想用这个简单的代码来获取最后一个错误的文本:

#include <cstdio>
#include <string>
#include <windows.h>

int main(){
    char err[256];
    memset(err, 0, 256);
    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, 255, NULL);
    wprintf(L"%s\n", err); // just for the safe case
    puts(err);
    return 0;
}

FormatMessage()尝试编写类似No error的内容,但我得到的是: WINE 中的┬√яюыэхэю єёях°эю下的╬яхЁрЎш  єёях°эю чртхЁ°хэр VirtualBox 中的WinXP

我检查了我的每个想法:1)in an example,由于某种原因,使用了wchar_t,所以我尝试创建wchar_t s的缓冲区,并且将其转换为FormatMessage (否则构建失败并显示cannot convert ‘wchar_t*’ to ‘LPSTR {aka char*}’ for argument ‘5’,2)然后我想,也许编码与GNU / Linux不同,所以我将WinXP安装到VirtualBox中;但是两个函数都没有任何可读性,应用程序一直在喃喃自语。

OS:Ubuntu(WINE),WinXP(VirtualBox)。编译器:MinGW GCC

UPD :我找到了正常工作的代码!

#include <cstdio>
#include <string>
#include <windows.h>

int main(){
    wchar_t err[256];
    memset(err, 0, 256);
    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, 255, NULL);
    int msgboxID = MessageBoxW( NULL,
                                err,
                                (LPCWSTR)L"☠",
                                MB_OK );
    return 0;
}

使用-mwindows标志编译后,它会在Ubuntu和WinXP中显示一个带有可读文本的消息框。所以,这个问题看起来只是终端问题。

3 个答案:

答案 0 :(得分:4)

您的终端设置为错误的代码页,代码页866中的序列┬√яюыэхэю是代码页1251中的Выполнено(即原始字节c2 fb ef ee eb ed e5 ed ee),通过调用

chcp 1251

在运行应用程序之前再试一次。

至于您的终端代码页与系统代码页不匹配的原因是任何人的猜测,请尝试通过删除HKCU \ Console注册表项来重置本地用户的cmd.exe设置(首先进行注册表备份以防万一)

答案 1 :(得分:2)

您必须使您的编码适应Windows API。

使用本机Windows编译器,可立即将错误识别为错误类型

声明:

TCHAR err[256];

TCHAR的#defined与windows.h中声明的所有其他函数一致。 This article解释了这种微软特定命名约定背后的原理。

Here您还可以看到FormatMessage()有两个版本:FormatMessageW(Unicode字符串,即wchar_t)和FormatMessageA(ANSI即char)。

修改 在交叉编译的情况下,应该关注#defines,这是在本地使用MSVC的情况下自动生成的。所以在包括windows.h之前不要忘记定义以下符号:WIN32,_CONSOLE,_UNICODE和UNICODE。

答案 2 :(得分:2)

看起来您正在混合使用Unicode和多字节字符集,您的代码应该类似于以下内容

int main() // unicode
{   wchar_t err[256];
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, 255, NULL);
    wprintf(L"%s\n", err);//just for the safe case
    _putws(err);
    return 0;
}

编辑:添加了MBCS版本

int main() // MBCS
{   char err[256];
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, 255, NULL);
    printf("%s\n", err);//just for the safe case
    puts(err);
    return 0;
}