Я просто пытаюсь получить текст последней ошибки с помощью этого простого кода:
#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. Таким образом, проблема выглядит только для терминала.
Ваш терминал настроен на неправильную кодовую страницу, последовательность ┬√яюыэхэю в кодовой странице 866 — Выполнено в кодовой странице 1251 (т.е. необработанные байты c2 fb ef ee eb ed e5 ed ee
), измените кодовую страницу терминала, позвонив
chcp 1251
прежде чем запустить приложение и попробуйте снова.
Что касается того, почему ваша кодовая страница терминала не соответствует вашей системной кодовой странице, можно только догадываться, попробуйте сбросить настройки cmd.exe для локального пользователя, удалив ключ реестра HKCU \ Console (на всякий случай сначала сделайте резервную копию реестра).
Похоже, что вы смешиваете 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;
}
Вы должны адаптировать свою кодировку к 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.