замечания
Каждый поток будет иметь свой последний код ошибки. Windows API установит последний код ошибки в вызывающем потоке.
Вы всегда должны вызывать GetLastError
сразу после проверки возвращаемого значения функции API Windows.
Большинство функций Windows API устанавливают последний код ошибки, когда они терпят неудачу. Некоторые также установят последний код ошибки, когда они преуспеют. Существует ряд функций, которые не устанавливают последний код ошибки. Всегда обращайтесь к документации по функциям Windows API.
Невозможно использовать FORMAT_MESSAGE_FROM_SYSTEM
без FORMAT_MESSAGE_IGNORE_INSERTS
при использовании функции FormatMessage
для получения описания кода ошибки.
Вступление
API Windows предоставляется с помощью C-вызываемого интерфейса. Успех или сбой вызова API сообщаются строго через возвращаемые значения. Исключения не являются частью документированного контракта (хотя некоторые реализации API могут вызывать исключения SEH , например, при передаче аргумента lpCommandLine только для чтения в CreateProcess ).
Сообщение об ошибке грубо относится к одной из четырех категорий:
- Только возвращаемое значение
- Возвращаемое значение с дополнительной информацией о сбое
- Возвращаемое значение с дополнительной информацией об отказе и успехе
- Возвращаемое значение
HRESULT
Документация для каждого вызова API явно вызывается, как сообщаются ошибки. Всегда обращайтесь к документации.
Ошибка, сообщенная только возвратным значением
Некоторые вызовы API возвращают единый флаг отказа / успеха без какой-либо дополнительной информации (например, GetObject ):
if ( GetObjectW( obj, 0, NULL ) == 0 ) {
// Failure: no additional information available.
}
Сообщается об ошибке с сообщением об ошибке
В дополнение к возвращаемому значению отказа / успеха некоторые вызовы API также устанавливают последнюю ошибку при сбое (например, CreateWindow ). Документация обычно содержит следующую стандартную формулировку для этого случая:
Если функция завершается успешно, возвращаемое значение <значение успеха API> .
Если функция не работает, возвращаемое значение <значение ошибки API> . Чтобы получить расширенную информацию об ошибке, вызовите GetLastError .
if ( CreateWindowW( ... ) == NULL ) {
// Failure: get additional information.
DWORD dwError = GetLastError();
} else {
// Success: must not call GetLastError.
}
Очень важно, что вы вызываете GetLastError()
НЕМЕДЛЕННО. Последний код ошибки может быть перезаписан любой другой функцией, поэтому, если есть дополнительная функция вызова между неудавшейся функцией и вызовом GetLastError()
, возврат из GetLastError()
больше не будет надежным. Будьте особенно осторожны при работе с конструкторами C ++.
Как только вы получите код ошибки, вам нужно будет его интерпретировать. Вы можете получить полный список кодов ошибок в MSDN на странице Системные коды ошибок (Windows) . Кроме того, вы можете посмотреть в своих файлах заголовков системы; файл со всеми константами кода ошибки — winerror.h
. (Если у вас есть официальный SDK от Microsoft для Windows 8 или новее, это находится в shared
папке с папкой include.)
Заметки о вызове GetLastError()
на других языках программирования
.net (C #, VB и т. д.)
С .net вы не должны P / Invoke в GetLastError()
напрямую. Это связано с тем, что среда выполнения .net сделает другие вызовы Windows API одним и тем же потоком за вашей спиной. Например, сборщик мусора может вызвать VirtualFree()
если он найдет достаточно памяти, которую он больше не использует, и это может произойти между вашим назначенным вызовом функции и вашим вызовом GetLastError()
.
Вместо этого .net предоставляет Marshal.GetLastWin32Error()
, которая будет извлекать последнюю ошибку из последнего вызова P / Invoke, который вы сами сделали. Используйте это вместо прямого вызова GetLastError()
.
(.net, похоже, не мешает вам импортировать GetLastError()
любом случае, я не уверен, почему.)
Идти
Различные средства, предоставляемые Go для вызова DLL-функций (которые находятся как в syscall
пакета, syscall
и в пакете golang.org/x/sys/windows
), возвращают три значения: r1
, r2
и err
. r2
никогда не используется; вы можете использовать пустой идентификатор. r1
— возвращаемое значение функции. err
является результатом вызова GetLastError()
но преобразуется в тип, реализующий error
, поэтому вы можете передать его вызывающим функциям для обработки.
Поскольку Go не знает, когда вызывать GetLastError()
а когда нет, он всегда будет возвращать ошибку nil
. Поэтому типичная идиома обработки ошибок Go
r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if err != nil {
// handle err
}
// use r1
не будет работать. Вместо этого вы должны проверить r1
точно так же, как и на C, и использовать только err
если это указывает, что функция возвратила ошибку:
r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if r1 == 0 {
// handle err
}
// use r1
Сообщается об ошибке с дополнительной информацией о сбоях и успехах
Некоторые вызовы API могут преуспеть или сбой более чем одним способом. API обычно возвращают дополнительную информацию как для успешных вызовов, так и для ошибок (например, CreateMutex ).
if ( CreateMutexW( NULL, TRUE, L"Global\MyNamedMutex" ) == NULL ) {
// Failure: get additional information.
DWORD dwError = GetLastError();
} else {
// Success: Determine which mutex was returned.
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
// Existing mutex object returned.
} else {
// Newly created mutex object returned.
}
}
Ошибка, сообщенная как значение HRESULT
HRESULT s — числовые 32-битные значения, где биты или диапазоны бит кодируют четко определенную информацию. MSB — это флаг отказа / успеха, а остальные бит хранят дополнительную информацию. Отказ или успех можно определить с помощью макросов FAILED или SUCCEEDED . HRESULT
s обычно используются совместно с COM, но также отображаются в реализациях, отличных от COM (например, StringCchPrintf ).
const size_t cchBuf = 5;
wchar_t buffer[cchBuf] = { 0 };
HRESULT hr = StringCchPrintfW( buffer, cchBuf, L"%s", L"Hello, world!" );
if ( FAILED( hr ) ) {
// Failure: Determine specific reason.
switch ( hr ) {
case STRSAFE_E_INSUFFICIENT_BUFFER:
// Buffer too small; increase buffer and retry.
...
case STRSAFE_E_INVALID_PARAMETER:
// Invalid parameter; implement custom error handling (e.g. logging).
...
default:
// Some other error code; implement custom error handling (e.g. logging).
...
}
}
Преобразование кода ошибки в строку сообщения
GetLastError
возвращает числовой код ошибки. Чтобы получить описательное сообщение об ошибке ( например , для отображения пользователю), вы можете вызвать FormatMessage
:
// This functions fills a caller-defined character buffer (pBuffer)
// of max length (cchBufferLength) with the human-readable error message
// for a Win32 error code (dwErrorCode).
//
// Returns TRUE if successful, or FALSE otherwise.
// If successful, pBuffer is guaranteed to be NUL-terminated.
// On failure, the contents of pBuffer are undefined.
BOOL GetErrorMessage(DWORD dwErrorCode, LPTSTR pBuffer, DWORD cchBufferLength)
{
if (cchBufferLength == 0)
{
return FALSE;
}
DWORD cchMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, /* (not used with FORMAT_MESSAGE_FROM_SYSTEM) */
dwErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
pBuffer,
cchBufferLength,
NULL);
return (cchMsg > 0);
}
В C ++ вы можете значительно упростить интерфейс, используя класс std::string
:
#include <Windows.h>
#include <exception>
#include <stdexcept>
#include <memory>
#include <string>
typedef std::basic_string<TCHAR> String;
String GetErrorMessage(DWORD dwErrorCode)
{
LPTSTR psz = NULL;
const DWORD cchMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, // (not used with FORMAT_MESSAGE_FROM_SYSTEM)
dwErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPTSTR>(&psz),
0,
NULL);
if (cchMsg > 0)
{
// Assign buffer to smart pointer with custom deleter so that memory gets released
// in case String's c'tor throws an exception.
auto deleter = [](void* p) { ::HeapFree(::GetProcessHeap(), 0, p); };
std::unique_ptr<TCHAR, decltype(deleter)> ptrBuffer(psz, deleter);
return String(ptrBuffer.get(), cchMsg);
}
else
{
throw std::runtime_error("Failed to retrieve error message string.");
}
}
ПРИМЕЧАНИЕ. Эти функции также работают для значений HRESULT
. Просто измените первый параметр из DWORD dwErrorCode
на HRESULT hResult
. Остальная часть кода может оставаться неизменной.
Опубликовано: 10 августа 2017
Исправлено: 10 августа 2017
Версия документа: 1.0
Когда ты вызываешь функцию Windows, она проверяет переданные ей параметры, а затем пытается выполнить свою работу. Если ты передал недопустимый параметр или если данную операцию нельзя выполнить по какой‐то другой причине, она возвращает значение, свидетельствующее об ошибке.
Типы данных для возвращаемых значений
Большинство функций Windows возвращают следующие типы:
- Процедуры:
- Подпрограммы‐процедуры Sub не возвращают значений. Такие функции всегда (или почти всегда) выполняется успешно, хотя их количество в Windows очень мало. Пример: функция ExitProcess.
- BOOL или Boolean:
- Если вызов функции оканчивается неудачей, то возвращается ложь False (она же 0), в остальных случаях возвращается любое другое число, отличное от нуля. Однако не пытайся сравнить это число с True, лучше просто сравнивать с нулём.
- HANDLE:
- Если вызов функции оканчивается неудачей, то обычно возвращается NULL, что эквивалентно нулю, в остальных случаях возвращаемое значение идентифицирует объект, которым ты можешь манипулировать. Однако некоторые функции вместо NULL в случае ошибки возвращают константу INVALID_HANDLE_VALUE, например, функция CreateFile. В документации для каждой функции чётко указано, что именно она возвращает при ошибке: NULL или INVALID_HANDLE_VALUE.
- PVOID или Any Ptr:
- Если вызов функции оканчивается неудачей, то возвращается NULL, в остальных случаях PVOID сообщает адрес блока данных в памяти.
- HRESULT:
- Если вызов функции оканчивается неудачей, то возвращается ошибочный код HRESULT, в остальных случаях значение говорит об успехе операции. Подробнее о HRESULT →
- Integer, Long или DWORD:
- Это значение — «крепкий орешек». Функции, которые возвращают значения каких‐либо счётчиков, обычно возвращают Integer, Long или DWORD. Если по какой‐либо причине функция не сумела сосчитать то, что ты хотел, она обычно возвращает 0 или -1, всё зависит от конкретной функции. Лучше всего проверь в документации, каким именно значением функция уведомляет об ошибке.
Почему же произошла ошибка?
При возникновении ошибки необходимо разобраться почему вызов данной функции оказался неудачен. За каждой ошибкой закреплён свой код — 32‐битное целое число.
Функция Windows, обнаружив ошибку, через механизм локальной памяти потока сопоставляет соответствующий код ошибки с вызывающим потоком. Это позволяет потокам работать независимо друг от друга, не вмешиваясь в чужие ошибки. Когда функция вернёт управление, её возвращаемое значение будет указывать на то, что произошла какая‐то ошибка. Какая именно — можно узнать, вызвав функцию GetLastError.
Declare Function GetLastError()As DWORD
Она просто возвращает числовое значение, характеризующее код ошибки.
Список кодов ошибок лежит в заголовочной файле winwinerror.bi
. Здесь приведена его небольшая часть, чтобы примерно представлять, на что он похож:
Const ERROR_SUCCESS = 0
Const NO_ERROR = 0
Const ERROR_INVALID_FUNCTION = 1
Const ERROR_FILE_NOT_FOUND = 2
Const ERROR_PATH_NOT_FOUND = 3
Const ERROR_TOO_MANY_OPEN_FILES = 4
Const ERROR_ACCESS_DENIED = 5
Const ERROR_INVALID_HANDLE = 6
Функцию GetLastError необходимо вызывать сразу же после неудачного вызова функции Windows, иначе код ошибки может быть потерян.
Некоторые функции Windows всегда завершаются успешно, но по разным причинам. Например, попытка создать объект ядра «событие» с определённым именем может быть успешна потому, что оно действительно создано, либо потому, что такой объект уже существует. Но иногда нужно знать причину успеха. Для возврата этой информации корпорация Microsoft предпочла использовать механизм установки кода последней ошибки. Так что и при успешном выполнении некоторых функций ты можешь использовать GetLastError и получать дополнительную информацию. К таким функциям относится, например, CreateEvent.
Ты наверняка спросишь, составит ли корпорация Microsoft полный список всех кодов ошибок, возможных в каждой функции. Ответ: нет. Такого списка никогда не будет, уж слишком сложно его составлять и поддерживать для всё новых и новых версий системы.
Проблема с подобным списком ещё и в том, что ты вызываешь одну функцию, а она может обратиться к другой, та — к следующей и так далее. Любая из этих функций может завершиться неудачно и по самым разным причинам. Иногда функция более высокого уровня сама справляется с ошибкой в одной из вызванных ею функций, и в конечном счёте выполняет то, что от неё хотели. В общем, для создания такого списка пришлось бы проследить цепочки вызовов в каждой функции, что очень трудно. А с появлением новой версии операционной системы цепочки вызовов пришлось бы пересматривать заново.
Определение собственных кодов ошибок
Механизм установки кода ошибки можно использовать и в собственных функциях. Предположим, ты пишешь библиотечную функцию, к которой будут обращаться другие части программы или вообще другие программы. Вызов этой функции по каким‐либо причинам может оказаться неудачным и тебе придётся тоже сообщать об этом. С этой целью ты просто устанавливаешь код последней ошибки в потоке и возвращаешь значение False, INVALID_HANDLE_VALUE, NULL или что‐то другое, более подходящее в твоём случае.
SetLastError
Чтобы установить код последней ошибки вызывай функцию SetLastError и передай ей нужной число.
Declare Sub SetLastError( _
ByVal dwErrorCode As DWORD _
)
Можно использовать коды ошибок, уже определённые в winerror.bi
, если они подходят. Если ты считаешь, что ни один из кодов ошибок из winerror.bi
не годится для ошибки, возможной в твоей функции, можно определить свой код.
Формат кода ошибки
Код ошибки представляет 32‐битное беззнаковое число, которое разбито на поля:
Биты числа | 31 30 | 29 | 28 | 27 26 25 24 23 22 21 20 19 18 17 16 | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
---|---|---|---|---|---|
Описание | Степень тяжести | Кем определён | Зарезервировано | Подсистема (facility code) | Код ошибки |
- Биты 30 и 31:
- Представляют собой степень тяжести ошибки. В двоичном виде: 00 — успех, 01 — информация, 10 — предупреждение, 11 — ошибка.
- Бит 29:
- Корпорация Microsoft обещала, что никогда не будет его устанавливать. Следовательно, если ты определяешь собственный код ошибки, то установи этот бит в 1 для гарантии, что твой код ошибки не будет конфликтовать с кодами, определёнными Microsoft.
- Бит 28:
- Зарезервирован. Должен быть 0.
- Биты с 16 по 27:
- Код подсистемы (facility code). Определяется корпорацией Microsoft. Указывает на компонент операционной системы, вызвавший ошибку.
- Биты с 0 по 15:
- Код ошибки. Определяется корпорацией Microsoft или пользователем.
Подробнее об этих полях будет рассказано в следующих статьях. На данный момент единственное важное для тебя поле — это бит 29. Чтобы гарантировать непересекаемость кодов ошибок от Microsoft, установи его в 1. В переводе на числа это означает, что твой код ошибки должен быть больше, чем &h20000000 или 536870912 в десятичном виде.
Получение описания ошибки
Для получения текстового описания ошибки подойдёт функция FormatMessage. Использовать её можно так:
#include "windows.bi"
Const BufferSize As Integer = 4096 - 1
' Строка с ошибкой
Dim ErrorMessage As WString * (BufferSize + 1) = Any
' Вызов функции с неправильным параметром
GetProcessId(NULL)
' Получить код ошибки
Dim dwError As DWORD = GetLastError()
' Получить строку по коду ошибки
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @ErrorMessage, BufferSize, NULL)
' Выводим описание ошибки на консоль
Print ErrorMessage
0
ERR_NO_ERROR
Нет ошибки
1
ERR_NO_RESULT
Нет ошибки, но результат неизвестен
2
ERR_COMMON_ERROR
Общая ошибка
3
ERR_INVALID_TRADE_PARAMETERS
Неправильные параметры
4
ERR_SERVER_BUSY
Торговый сервер занят
5
ERR_OLD_VERSION
Старая версия клиентского терминала
6
ERR_NO_CONNECTION
Нет связи с торговым сервером
7
ERR_NOT_ENOUGH_RIGHTS
Недостаточно прав
8
ERR_TOO_FREQUENT_REQUESTS
Слишком частые запросы
9
ERR_MALFUNCTIONAL_TRADE
Недопустимая операция, нарушающая функционирование сервера
64
ERR_ACCOUNT_DISABLED
Счет заблокирован
65
ERR_INVALID_ACCOUNT
Неправильный номер счета
128
ERR_TRADE_TIMEOUT
Истек срок ожидания совершения сделки
129
ERR_INVALID_PRICE
Неправильная цена
130
ERR_INVALID_STOPS
Неправильные стопы
131
ERR_INVALID_TRADE_VOLUME
Неправильный объем
132
ERR_MARKET_CLOSED
Рынок закрыт
133
ERR_TRADE_DISABLED
Торговля запрещена
134
ERR_NOT_ENOUGH_MONEY
Недостаточно денег для совершения операции
135
ERR_PRICE_CHANGED
Цена изменилась
136
ERR_OFF_QUOTES
Нет цен
137
ERR_BROKER_BUSY
Брокер занят
138
ERR_REQUOTE
Новые цены
139
ERR_ORDER_LOCKED
Ордер заблокирован и уже обрабатывается
140
ERR_LONG_POSITIONS_ONLY_ALLOWED
Разрешена только покупка
141
ERR_TOO_MANY_REQUESTS
Слишком много запросов
145
ERR_TRADE_MODIFY_DENIED
Модификация запрещена, так как ордер слишком близок к рынку
146
ERR_TRADE_CONTEXT_BUSY
Подсистема торговли занята
147
ERR_TRADE_EXPIRATION_DENIED
Использование даты истечения ордера запрещено брокером
148
ERR_TRADE_TOO_MANY_ORDERS
Количество открытых и отложенных ордеров достигло предела, установленного брокером
149
ERR_TRADE_HEDGE_PROHIBITED
Попытка открыть противоположный ордер в случае, если хеджирование запрещено
150
ERR_TRADE_PROHIBITED_BY_FIFO
Попытка закрыть позицию по инструменту в противоречии с правилом FIFO
4000
ERR_NO_MQLERROR
Нет ошибки
4001
ERR_WRONG_FUNCTION_POINTER
Неправильный указатель функции
4002
ERR_ARRAY_INDEX_OUT_OF_RANGE
Индекс массива — вне диапазона
4003
ERR_NO_MEMORY_FOR_CALL_STACK
Нет памяти для стека функций
4004
ERR_RECURSIVE_STACK_OVERFLOW
Переполнение стека после рекурсивного вызова
4005
ERR_NOT_ENOUGH_STACK_FOR_PARAM
На стеке нет памяти для передачи параметров
4006
ERR_NO_MEMORY_FOR_PARAM_STRING
Нет памяти для строкового параметра
4007
ERR_NO_MEMORY_FOR_TEMP_STRING
Нет памяти для временной строки
4008
ERR_NOT_INITIALIZED_STRING
Неинициализированная строка
4009
ERR_NOT_INITIALIZED_ARRAYSTRING
Неинициализированная строка в массиве
4010
ERR_NO_MEMORY_FOR_ARRAYSTRING
Нет памяти для строкового массива
4011
ERR_TOO_LONG_STRING
Слишком длинная строка
4012
ERR_REMAINDER_FROM_ZERO_DIVIDE
Остаток от деления на ноль
4013
ERR_ZERO_DIVIDE
Деление на ноль
4014
ERR_UNKNOWN_COMMAND
Неизвестная команда
4015
ERR_WRONG_JUMP
Неправильный переход
4016
ERR_NOT_INITIALIZED_ARRAY
Неинициализированный массив
4017
ERR_DLL_CALLS_NOT_ALLOWED
Вызовы DLL не разрешены
4018
ERR_CANNOT_LOAD_LIBRARY
Невозможно загрузить библиотеку
4019
ERR_CANNOT_CALL_FUNCTION
Невозможно вызвать функцию
4020
ERR_EXTERNAL_CALLS_NOT_ALLOWED
Вызовы внешних библиотечных функций не разрешены
4021
ERR_NO_MEMORY_FOR_RETURNED_STR
Недостаточно памяти для строки, возвращаемой из функции
4022
ERR_SYSTEM_BUSY
Система занята
4023
ERR_DLLFUNC_CRITICALERROR
Критическая ошибка вызова DLL-функции
4024
ERR_INTERNAL_ERROR
Внутренняя ошибка
4025
ERR_OUT_OF_MEMORY
Нет памяти
4026
ERR_INVALID_POINTER
Неверный указатель
4027
ERR_FORMAT_TOO_MANY_FORMATTERS
Слишком много параметров форматирования строки
4028
ERR_FORMAT_TOO_MANY_PARAMETERS
Число параметров превышает число параметров форматирования строки
4029
ERR_ARRAY_INVALID
Неверный массив
4030
ERR_CHART_NOREPLY
График не отвечает
4050
ERR_INVALID_FUNCTION_PARAMSCNT
Неправильное количество параметров функции
4051
ERR_INVALID_FUNCTION_PARAMVALUE
Недопустимое значение параметра функции
4052
ERR_STRING_FUNCTION_INTERNAL
Внутренняя ошибка строковой функции
4053
ERR_SOME_ARRAY_ERROR
Ошибка массива
4054
ERR_INCORRECT_SERIESARRAY_USING
Неправильное использование массива-таймсерии
4055
ERR_CUSTOM_INDICATOR_ERROR
Ошибка пользовательского индикатора
4056
ERR_INCOMPATIBLE_ARRAYS
Массивы несовместимы
4057
ERR_GLOBAL_VARIABLES_PROCESSING
Ошибка обработки глобальных переменных
4058
ERR_GLOBAL_VARIABLE_NOT_FOUND
Глобальная переменная не обнаружена
4059
ERR_FUNC_NOT_ALLOWED_IN_TESTING
Функция не разрешена в тестовом режиме
4060
ERR_FUNCTION_NOT_CONFIRMED
Функция не разрешена
4061
ERR_SEND_MAIL_ERROR
Ошибка отправки почты
4062
ERR_STRING_PARAMETER_EXPECTED
Ожидается параметр типа string
4063
ERR_INTEGER_PARAMETER_EXPECTED
Ожидается параметр типа integer
4064
ERR_DOUBLE_PARAMETER_EXPECTED
Ожидается параметр типа double
4065
ERR_ARRAY_AS_PARAMETER_EXPECTED
В качестве параметра ожидается массив
4066
ERR_HISTORY_WILL_UPDATED
Запрошенные исторические данные в состоянии обновления
4067
ERR_TRADE_ERROR
Ошибка при выполнении торговой операции
4068
ERR_RESOURCE_NOT_FOUND
Ресурс не найден
4069
ERR_RESOURCE_NOT_SUPPORTED
Ресурс не поддерживается
4070
ERR_RESOURCE_DUPLICATED
Дубликат ресурса
4071
ERR_INDICATOR_CANNOT_INIT
Ошибка инициализации пользовательского индикатора
4072
ERR_INDICATOR_CANNOT_LOAD
Ошибка загрузки пользовательского индикатора
4073
ERR_NO_HISTORY_DATA
Нет исторических данных
4074
ERR_NO_MEMORY_FOR_HISTORY
Не хватает памяти для исторических данных
4075
ERR_NO_MEMORY_FOR_INDICATOR
Не хватает памяти для расчёта индикатора
4099
ERR_END_OF_FILE
Конец файла
4100
ERR_SOME_FILE_ERROR
Ошибка при работе с файлом
4101
ERR_WRONG_FILE_NAME
Неправильное имя файла
4102
ERR_TOO_MANY_OPENED_FILES
Слишком много открытых файлов
4103
ERR_CANNOT_OPEN_FILE
Невозможно открыть файл
4104
ERR_INCOMPATIBLE_FILEACCESS
Несовместимый режим доступа к файлу
4105
ERR_NO_ORDER_SELECTED
Ни один ордер не выбран
4106
ERR_UNKNOWN_SYMBOL
Неизвестный символ
4107
ERR_INVALID_PRICE_PARAM
Неправильный параметр цены для торговой функции
4108
ERR_INVALID_TICKET
Неверный номер тикета
4109
ERR_TRADE_NOT_ALLOWED
Торговля не разрешена. Необходимо включить опцию «Разрешить советнику торговать» в свойствах эксперта
4110
ERR_LONGS_NOT_ALLOWED
Ордера на покупку не разрешены. Необходимо проверить свойства эксперта
4111
ERR_SHORTS_NOT_ALLOWED
Ордера на продажу не разрешены. Необходимо проверить свойства эксперта
4112
ERR_TRADE_EXPERT_DISABLED_BY_SERVER
Автоматическая торговля с помощью экспертов/скриптов запрещена на стороне сервера
4200
ERR_OBJECT_ALREADY_EXISTS
Объект уже существует
4201
ERR_UNKNOWN_OBJECT_PROPERTY
Запрошено неизвестное свойство объекта
4202
ERR_OBJECT_DOES_NOT_EXIST
Объект не существует
4203
ERR_UNKNOWN_OBJECT_TYPE
Неизвестный тип объекта
4204
ERR_NO_OBJECT_NAME
Нет имени объекта
4205
ERR_OBJECT_COORDINATES_ERROR
Ошибка координат объекта
4206
ERR_NO_SPECIFIED_SUBWINDOW
Не найдено указанное подокно
4207
ERR_SOME_OBJECT_ERROR
Ошибка при работе с объектом
4210
ERR_CHART_PROP_INVALID
Неизвестное свойство графика
4211
ERR_CHART_NOT_FOUND
График не найден
4212
ERR_CHARTWINDOW_NOT_FOUND
Не найдено подокно графика
4213
ERR_CHARTINDICATOR_NOT_FOUND
Индикатор не найден
4220
ERR_SYMBOL_SELECT
Ошибка выбора инструмента
4250
ERR_NOTIFICATION_ERROR
Ошибка отправки push-уведомления
4251
ERR_NOTIFICATION_PARAMETER
Ошибка параметров push-уведомления
4252
ERR_NOTIFICATION_SETTINGS
Уведомления запрещены
4253
ERR_NOTIFICATION_TOO_FREQUENT
Слишком частые запросы отсылки push-уведомлений
4260
ERR_FTP_NOSERVER
Не указан FTP сервер
4261
ERR_FTP_NOLOGIN
Не указан FTP логин
4262
ERR_FTP_CONNECT_FAILED
Ошибка при подключении к FTP серверу
4263
ERR_FTP_CLOSED
Подключение к FTP серверу закрыто
4264
ERR_FTP_CHANGEDIR
На FTP сервере не найдена директория для выгрузки файла
4265
ERR_FTP_FILE_ERROR
Не найден файл в директории MQL4Files для отправки на FTP сервер
4266
ERR_FTP_ERROR
Ошибка при передаче файла на FTP сервер
5001
ERR_FILE_TOO_MANY_OPENED
Слишком много открытых файлов
5002
ERR_FILE_WRONG_FILENAME
Неверное имя файла
5003
ERR_FILE_TOO_LONG_FILENAME
Слишком длинное имя файла
5004
ERR_FILE_CANNOT_OPEN
Ошибка открытия файла
5005
ERR_FILE_BUFFER_ALLOCATION_ERROR
Ошибка размещения буфера текстового файла
5006
ERR_FILE_CANNOT_DELETE
Ошибка удаления файла
5007
ERR_FILE_INVALID_HANDLE
Неверный хендл файла (файл закрыт или не был открыт)
5008
ERR_FILE_WRONG_HANDLE
Неверный хендл файла (индекс хендла отсутствует в таблице)
5009
ERR_FILE_NOT_TOWRITE
Файл должен быть открыт с флагом FILE_WRITE
5010
ERR_FILE_NOT_TOREAD
Файл должен быть открыт с флагом FILE_READ
5011
ERR_FILE_NOT_BIN
Файл должен быть открыт с флагом FILE_BIN
5012
ERR_FILE_NOT_TXT
Файл должен быть открыт с флагом FILE_TXT
5013
ERR_FILE_NOT_TXTORCSV
Файл должен быть открыт с флагом FILE_TXT или FILE_CSV
5014
ERR_FILE_NOT_CSV
Файл должен быть открыт с флагом FILE_CSV
5015
ERR_FILE_READ_ERROR
Ошибка чтения файла
5016
ERR_FILE_WRITE_ERROR
Ошибка записи файла
5017
ERR_FILE_BIN_STRINGSIZE
Размер строки должен быть указан для двоичных файлов
5018
ERR_FILE_INCOMPATIBLE
Неверный тип файла (для строковых массивов-TXT, для всех других-BIN)
5019
ERR_FILE_IS_DIRECTORY
Файл является директорией
5020
ERR_FILE_NOT_EXIST
Файл не существует
5021
ERR_FILE_CANNOT_REWRITE
Файл не может быть перезаписан
5022
ERR_FILE_WRONG_DIRECTORYNAME
Неверное имя директории
5023
ERR_FILE_DIRECTORY_NOT_EXIST
Директория не существует
5024
ERR_FILE_NOT_DIRECTORY
Указанный файл не является директорией
5025
ERR_FILE_CANNOT_DELETE_DIRECTORY
Ошибка удаления директории
5026
ERR_FILE_CANNOT_CLEAN_DIRECTORY
Ошибка очистки директории
5027
ERR_FILE_ARRAYRESIZE_ERROR
Ошибка изменения размера массива
5028
ERR_FILE_STRINGRESIZE_ERROR
Ошибка изменения размера строки
5029
ERR_FILE_STRUCT_WITH_OBJECTS
Структура содержит строки или динамические массивы
5200
ERR_WEBREQUEST_INVALID_ADDRESS
URL не прошел проверку
5201
ERR_WEBREQUEST_CONNECT_FAILED
Не удалось подключиться к указанному URL
5202
ERR_WEBREQUEST_TIMEOUT
Превышен таймаут получения данных
5203
ERR_WEBREQUEST_REQUEST_FAILED
Ошибка в результате выполнения HTTP запроса
Пользовательские ошибки
65536
ERR_USER_ERROR_FIRST
С этого кода начинаются ошибки, задаваемые пользователем