Win32 API: GetLastError () с FormatMessage () печатает мусор

Я просто пытаюсь получить текст последней ошибки с помощью этого простого кода:

#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, но вместо этого я получаю: ┬√яюыэхэю єёях°эю в ВИНО, а также ╬яхЁрЎш  єёях°эю чртхЁ°хэр под WinXP в VirtualBox.

Я проверил каждую мою идею: 1) в примере, по какой-то причине wchar_t используется, поэтому я попытался создать буфер wchar_tс, и приведение его к 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. Таким образом, проблема выглядит только для терминала.

2

Решение

Ваш терминал настроен на неправильную кодовую страницу, последовательность ┬√яюыэхэю в кодовой странице 866 — Выполнено в кодовой странице 1251 (т.е. необработанные байты c2 fb ef ee eb ed e5 ed ee), измените кодовую страницу терминала, позвонив

chcp 1251

прежде чем запустить приложение и попробуйте снова.

Что касается того, почему ваша кодовая страница терминала не соответствует вашей системной кодовой странице, можно только догадываться, попробуйте сбросить настройки cmd.exe для локального пользователя, удалив ключ реестра HKCU \ Console (на всякий случай сначала сделайте резервную копию реестра).

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;
}
2

Вы должны адаптировать свою кодировку к Windows API.

При использовании собственного компилятора Windows ошибка сразу обнаруживается как неправильный тип

Объявляет:

TCHAR err[256];

TCHAR # определен, чтобы быть совместимым со всеми другими функциями, объявленными в windows.h. Эта статья объясняет принцип, лежащий в основе этого соглашения Microsoft о присвоении имен.

Вот Вы также можете видеть, что существует две версии FormatMessage (): FormatMessageW (строки Unicode, т.е. wchar_t) и FormatMessageA (ANSI, то есть char).

Редактировать:
В случае кросс-компиляции следует уделить внимание перикулярной #defines, которые генерируются автоматически в случае собственного использования MSVC. Поэтому не забудьте определить следующие символы перед включением windows.h: WIN32, _CONSOLE, _UNICODE и UNICODE.

2
По вопросам рекламы [email protected]