【问题标题】:Win32 API: GetLastError() with FormatMessage() prints a junkWin32 API:GetLastError() 与 FormatMessage() 打印垃圾
【发布时间】:2014-10-06 13:21:25
【问题描述】:

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

#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 中的┬√яюыэхэю єёях°эюWinXP 中的╬яхЁрЎш  єёях°эю чртхЁ°хэр >虚拟框。

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

操作系统: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 中显示一个带有可读文本的消息框。所以,问题看起来只是终端问题。

【问题讨论】:

  • 这可能是编码不匹配,chcp 的输出给你什么?
  • @molbdnilo 在本机windows上执行,在没有最后一个错误的情况下得到“操作成功”的消息是一个惊喜。
  • @Hi-Angel,是的,您的代码,但是使用如下所述的 TCHAR 并且 puts() 被注释掉了。您可以在这里找到确切的消息:msdn.microsoft.com/en-us/library/windows/desktop/…
  • @Hi-Angel 鉴于您在问题中发布的文本仅在第 866 页的 0x80-0xFF 范围内,这几乎可以肯定是终端代码页问题,请查看我在上面链接的页面西里尔文和俄文代码页,并使用chcp 尝试每个代码页,每次都再次运行您的应用程序。
  • @Hi-Angel:如果您浏览System Error Codes,您会发现一些包含占位符的消息(例如ERROR_BAD_EXE_FORMAT“%1 不是有效的 Win32 应用程序。”我>)。系统没有提供查询占位符个数和数据类型的接口,这使得占位符本质上是无用的。

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


【解决方案1】:

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

chcp 1251

在你运行你的应用之前再试一次。

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

【讨论】:

  • 嗯,你是对的。因此,为了使程序在 WINE 中运行,我需要像这样启动LANG=ru_RU.cp1251 wine a.exe(其中 a.exe 是要启动的应用程序) 不幸的是,这样做了在 Windows 中不是技巧;无论如何,我认为我可以接受答案,因为这证明如果应用程序的用户看不到输出,他只是编码错误。无论哪种方式,我需要的终端输出仅用于调试,当然,在发行版中我将使用 GUI。而且,正如我在更新中显示的那样,GUI 在编码方面工作得很好。
  • @Hi-Angel 对了,我忘了你用的是酒,反正一切都好,结果好!为了将来参考,您可能需要考虑定义 UNICODE 宏并使用宽字符串来完全避免这种情况。
  • user657267,wchar_ts 的 unicode 在终端中也不起作用;)
【解决方案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。

【讨论】:

  • 唉,它没有改变输出。
  • Hhm... 如果您在文件的开头#define WIN32#define _CONSOLE#define _UNICODE#define UNICODE,在包含 windows.h 之前?我的原生 Windows 编译器上有预定义的设置。
  • 嗯...我刚刚发现使用@EdwardClements 的代码(但使用FormatMessageW() 函数_putws(err) 什么也不打印(但它在wine 下打印K?&gt;;=5=&gt; CA?5H=&gt;.)。应该打印什么什么时候没有错误?
  • 该消息是特定于语言的,但类似于“操作成功”。顺便说一句,您是否尝试过使用上面的附加 #defines ?
  • 是的,这些定义不会改变输出。尝试了我目前拥有的两个版本的功能。
【解决方案3】:

您似乎在混合使用 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;
}

【讨论】:

  • 我复制了你所有的代码(只是添加了一个演员表),但输出仍然相同:( 注意:你的代码没有编译,因为你错过了演员表对于论点 5,我在帖子中提到了类似的情况。
  • 添加演员表不是正确的方法——你的项目是 Unicode 还是 MBCS?
  • 我已经写了一条评论,但突然想到:你的问题是什么意思?这是否意味着在 Unicode 的 Windows 下我需要在编译时添加一些标志?是的,我想要一个 Unicode。
  • 我不太确定其他环境,但是在Windows(Visual Studio)中,有一个设置“字符集”,我建议将其设置为“使用Unicode字符集”;其他操作系统和编译器可能有相同的设置
  • 其实没有,IDE只是创建了一个工程文件(.vcxproj),编译源码的命令行就在里面(/ZI /nologo /W3 /WX- /Od /Oy- /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "_AFXDLL" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yu"StdAfx.h" /Fp"Debug\www.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue);当我运行代码时,我的控制台上显示“操作成功完成”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 2013-12-23
  • 1970-01-01
  • 1970-01-01
  • 2015-06-28
  • 2016-05-16
相关资源
最近更新 更多