450 lines
20 KiB
Plaintext
450 lines
20 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| ControlErrors.mqh |
|
|
//| Copyright KlimMalgin |
|
|
//| The library should be located in directory: |
|
|
//| MetaTrader 5/MQL5/Include/ |
|
|
//| https://www.mql5.com/en/articles/70 |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "KlimMalgin"
|
|
#property link ""
|
|
|
|
|
|
|
|
class ControlErrors
|
|
{
|
|
private:
|
|
|
|
// Flags that define what types of reports need to be enabled
|
|
bool _PlaySound; // Play or don't play a sound when an error occurs.
|
|
bool _PrintInfo; // Add error details to the journal of Expert Advisors
|
|
bool _AlertInfo; // Generate Alert with error details
|
|
bool _WriteFile; // Record reports on errors into a file or not
|
|
|
|
// A structure for storing error data elements that use this structure
|
|
struct Code
|
|
{
|
|
int code; // Error code
|
|
string desc; // Description of the error code
|
|
};
|
|
Code Errors[]; // Array that contains error codes and their descriptions
|
|
Code _UserError; // Stores information about a custome error
|
|
Code _Error; // Stores information about the last error of any type
|
|
|
|
// Different service properties
|
|
short _CountErrors; // Number of errors stored in array Errors[]
|
|
string _PlaySoundFile; // File that will be played for an alert sound
|
|
string _DataPath; // Path to the log storing directory
|
|
|
|
|
|
public:
|
|
// Constructor
|
|
ControlErrors(void);
|
|
|
|
// Methods for setting flags
|
|
void SetSound(bool value); // Play or don't play a sound when an error occurs
|
|
void SetPrint(bool value); // Enter error data the the journal of Expert Advisors or not
|
|
void SetAlert(bool value); // Generate an Alert message or not
|
|
void SetWriteFlag(bool flag); // Set the writing flag. true - keep logs, false - do not keep
|
|
|
|
// Methods for working with errors
|
|
int mGetLastError(); // Returns contents of the system variable _LastError
|
|
int mGetError(); // Returns code of the last obtained error
|
|
int mGetTypeError(); // Returns error type (Custom = 1 ore predefined = 0)
|
|
void mResetLastError(); // Resets the contents of the system variable _LastError
|
|
void mSetUserError(ushort value, string desc = ""); // Sets the custom error
|
|
void mResetUserError(); // Resets class fields that contain information about the custom error
|
|
void mResetError(); // Resets the structure that contains information about the last error
|
|
string mGetDesc(int nErr = 0); // Returns error description by the number, or that of the current error of no number
|
|
int Check(string st = ""); // Method to check the current system state for errors
|
|
|
|
// Alert methods (Alert, Print, Sound)
|
|
void mAlert(string message = "");
|
|
void mPrint(string message = "");
|
|
void mSound();
|
|
|
|
// Various service methods
|
|
void SetPlaySoundFile(string file); // Method sets the file name to play an sound
|
|
void SetWritePath(string path); // Set the path to store logs
|
|
int mFileWrite(string message = "");// Record into a file the available information about the last error
|
|
};
|
|
|
|
void ControlErrors::ControlErrors(void)
|
|
{
|
|
SetAlert(false);
|
|
SetPrint(false);
|
|
SetSound(false);
|
|
SetWriteFlag(false);
|
|
SetPlaySoundFile("alert.wav");
|
|
SetWritePath("LogErrors.txt");
|
|
|
|
_CountErrors = 150;
|
|
|
|
ArrayResize(Errors, _CountErrors);
|
|
// Return codes of a trade server
|
|
Errors[0].code = 10004;Errors[0].desc = "Requote";
|
|
Errors[1].code = 10006;Errors[1].desc = "Request rejected";
|
|
Errors[2].code = 10007;Errors[2].desc = "Request canceled by trader";
|
|
Errors[3].code = 10008;Errors[3].desc = "Order placed";
|
|
Errors[4].code = 10009;Errors[4].desc = "Request is completed";
|
|
Errors[5].code = 10010;Errors[5].desc = "Request is partially completed";
|
|
Errors[6].code = 10011;Errors[6].desc = "Request processing error";
|
|
Errors[7].code = 10012;Errors[7].desc = "Request canceled by timeout";
|
|
Errors[8].code = 10013;Errors[8].desc = "Invalid request";
|
|
Errors[9].code = 10014;Errors[9].desc = "Invalid volume in the request";
|
|
Errors[10].code = 10015;Errors[10].desc = "Invalid price in the request";
|
|
Errors[11].code = 10016;Errors[11].desc = "Invalid stops in the request";
|
|
Errors[12].code = 10017;Errors[12].desc = "Trade is disabled";
|
|
Errors[13].code = 10018;Errors[13].desc = "Market is closed";
|
|
Errors[14].code = 10019;Errors[14].desc = "There is not enough money to fulfill the request";
|
|
Errors[15].code = 10020;Errors[15].desc = "Prices changed";
|
|
Errors[16].code = 10021;Errors[16].desc = "There are no quotes to process the request";
|
|
Errors[17].code = 10022;Errors[17].desc = "Invalid order expiration date in the request";
|
|
Errors[18].code = 10023;Errors[18].desc = "Order state changed";
|
|
Errors[19].code = 10024;Errors[19].desc = "Too frequent requests";
|
|
Errors[20].code = 10025;Errors[20].desc = "No changes in request";
|
|
Errors[21].code = 10026;Errors[21].desc = "Autotrading disabled by server";
|
|
Errors[22].code = 10027;Errors[22].desc = "Autotrading disabled by client terminal";
|
|
Errors[23].code = 10028;Errors[23].desc = "Request locked for processing";
|
|
Errors[24].code = 10029;Errors[24].desc = "Order or position frozen";
|
|
Errors[25].code = 10030;Errors[25].desc = "Invalid order filling type";
|
|
|
|
// Common Errors
|
|
Errors[26].code = 4001;Errors[26].desc = "Unexpected internal error";
|
|
Errors[27].code = 4002;Errors[27].desc = "Wrong parameter in the inner call of the client terminal function";
|
|
Errors[28].code = 4003;Errors[28].desc = "Wrong parameter when calling the system function";
|
|
Errors[29].code = 4004;Errors[29].desc = "Not enough memory to perform the system function";
|
|
Errors[30].code = 4005;Errors[30].desc = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes";
|
|
Errors[31].code = 4006;Errors[31].desc = "Array of a wrong type, wrong size, or a damaged object of a dynamic array";
|
|
Errors[32].code = 4007;Errors[32].desc = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array";
|
|
Errors[33].code = 4008;Errors[33].desc = "Not enough memory for the relocation of string";
|
|
Errors[34].code = 4009;Errors[34].desc = "Not initialized string";
|
|
Errors[35].code = 4010;Errors[35].desc = "Invalid date and/or time";
|
|
Errors[36].code = 4011;Errors[36].desc = "Requested array size exceeds 2 GB";
|
|
Errors[37].code = 4012;Errors[37].desc = "Wrong pointer";
|
|
Errors[38].code = 4013;Errors[38].desc = "Wrong type of pointer";
|
|
Errors[39].code = 4014;Errors[39].desc = "System function is not allowed to call";
|
|
|
|
// Charts
|
|
Errors[40].code = 4101;Errors[40].desc = "Wrong chart ID";
|
|
Errors[41].code = 4102;Errors[41].desc = "Chart does not respond";
|
|
Errors[42].code = 4103;Errors[42].desc = "Chart not found";
|
|
Errors[43].code = 4104;Errors[43].desc = "No Expert Advisor in the chart that could handle the event";
|
|
Errors[44].code = 4105;Errors[44].desc = "Chart opening error";
|
|
Errors[45].code = 4106;Errors[45].desc = "Failed to change chart symbol and period";
|
|
Errors[46].code = 4107;Errors[46].desc = "Wrong parameter for timer";
|
|
Errors[47].code = 4108;Errors[47].desc = "Failed to create timer";
|
|
Errors[48].code = 4109;Errors[48].desc = "Wrong chart property ID";
|
|
Errors[49].code = 4110;Errors[49].desc = "Error creating screenshots";
|
|
Errors[50].code = 4111;Errors[50].desc = "Error navigating through chart";
|
|
Errors[51].code = 4112;Errors[51].desc = "Error applying template";
|
|
Errors[52].code = 4113;Errors[52].desc = "Subwindow containing the indicator was not found";
|
|
|
|
// Graphical Objects
|
|
Errors[53].code = 4201;Errors[53].desc = "Error working with a graphical object";
|
|
Errors[54].code = 4202;Errors[54].desc = "Graphical object was not found";
|
|
Errors[55].code = 4203;Errors[55].desc = "Wrong ID of a graphical object property";
|
|
Errors[56].code = 4204;Errors[56].desc = "Unable to get date corresponding to the value";
|
|
Errors[57].code = 4205;Errors[57].desc = "Unable to get value corresponding to the date";
|
|
|
|
// MarketInfo
|
|
Errors[58].code = 4301;Errors[58].desc = "Unknown symbol";
|
|
Errors[59].code = 4302;Errors[59].desc = "Symbol is not selected in MarketWatch";
|
|
Errors[60].code = 4303;Errors[60].desc = "Wrong identifier of a symbol property";
|
|
Errors[61].code = 4304;Errors[61].desc = "Time of the last tick is not known (no ticks)";
|
|
|
|
// History Access
|
|
Errors[62].code = 4401;Errors[62].desc = "Requested history not found";
|
|
Errors[63].code = 4402;Errors[63].desc = "Wrong ID of the history property";
|
|
|
|
// Global_Variables
|
|
Errors[64].code = 4501;Errors[64].desc = "Global variable of the client terminal is not found";
|
|
Errors[65].code = 4502;Errors[65].desc = "Global variable of the client terminal with the same name already exists";
|
|
Errors[66].code = 4510;Errors[66].desc = "Email sending failed";
|
|
Errors[67].code = 4511;Errors[67].desc = "Sound playing failed";
|
|
Errors[68].code = 4512;Errors[68].desc = "Wrong identifier of the program property";
|
|
Errors[69].code = 4513;Errors[69].desc = "Wrong identifier of the terminal property";
|
|
Errors[70].code = 4514;Errors[70].desc = "File sending via ftp failed";
|
|
|
|
// Custom Indicator Buffers
|
|
Errors[71].code = 4601;Errors[71].desc = "Not enough memory for the distribution of indicator buffers";
|
|
Errors[72].code = 4602;Errors[72].desc = "Wrong indicator buffer index";
|
|
|
|
// Custom Indicator Properties
|
|
Errors[73].code = 4603;Errors[73].desc = "Wrong ID of the custom indicator property";
|
|
|
|
// Account
|
|
Errors[74].code = 4701;Errors[74].desc = "Wrong account property ID";
|
|
Errors[75].code = 4751;Errors[75].desc = "Wrong trade property ID;";
|
|
Errors[76].code = 4752;Errors[76].desc = "Trading by Expert Advisors prohibited";
|
|
Errors[77].code = 4753;Errors[77].desc = "Position not found";
|
|
Errors[78].code = 4754;Errors[78].desc = "Order not found";
|
|
Errors[79].code = 4755;Errors[79].desc = "Deal not found";
|
|
Errors[80].code = 4756;Errors[80].desc = "Trade request sending failed";
|
|
Errors[81].code = 4757;Errors[81].desc = "Timeout exceeded when selecting (searching) specified data";
|
|
|
|
// Indicators
|
|
Errors[82].code = 4801;Errors[82].desc = "Unknown symbol";
|
|
Errors[83].code = 4802;Errors[83].desc = "Indicator cannot be created";
|
|
Errors[84].code = 4803;Errors[84].desc = "Not enough memory to add the indicator";
|
|
Errors[85].code = 4804;Errors[85].desc = "The indicator cannot be applied to another indicator";
|
|
Errors[86].code = 4805;Errors[86].desc = "Error applying an indicator to chart";
|
|
Errors[87].code = 4806;Errors[87].desc = "Requested data not found";
|
|
Errors[88].code = 4807;Errors[88].desc = "Wrong index of the requested indicator buffer";
|
|
Errors[89].code = 4808;Errors[89].desc = "Wrong number of parameters when creating an indicator";
|
|
Errors[90].code = 4809;Errors[90].desc = "No parameters when creating an indicator";
|
|
Errors[91].code = 4810;Errors[91].desc = "The first parameter in the array must be the name of the custom indicator";
|
|
Errors[92].code = 4811;Errors[92].desc = "Invalid parameter type in the array when creating an indicator";
|
|
|
|
// Depth of Market
|
|
Errors[93].code = 4901;Errors[93].desc = "Depth Of Market can not be added";
|
|
Errors[94].code = 4902;Errors[94].desc = "Depth Of Market can not be removed";
|
|
Errors[95].code = 4903;Errors[95].desc = "The data from Depth Of Market can not be obtained";
|
|
Errors[96].code = 4904;Errors[96].desc = "Error in subscribing to receive new data from Depth Of Market";
|
|
|
|
// File Operations
|
|
Errors[97].code = 5001;Errors[97].desc = "More than 64 files cannot be opened at the same time";
|
|
Errors[98].code = 5002;Errors[98].desc = "Invalid file name";
|
|
Errors[99].code = 5003;Errors[99].desc = "Too long file name";
|
|
Errors[100].code = 5004;Errors[100].desc = "File opening error";
|
|
Errors[101].code = 5005;Errors[101].desc = "Not enough memory for cache to read";
|
|
Errors[102].code = 5006;Errors[102].desc = "File deleting error";
|
|
Errors[103].code = 5007;Errors[103].desc = "A file with this handle was closed, or was not opened at all";
|
|
Errors[104].code = 5008;Errors[104].desc = "Wrong file handle";
|
|
Errors[105].code = 5009;Errors[105].desc = "The file must be opened for writing";
|
|
Errors[106].code = 5010;Errors[106].desc = "The file must be opened for reading";
|
|
Errors[107].code = 5011;Errors[107].desc = "The file must be opened as a binary one";
|
|
Errors[108].code = 5012;Errors[108].desc = "The file must be opened as a text";
|
|
Errors[109].code = 5013;Errors[109].desc = "The file must be opened as a text or CSV";
|
|
Errors[110].code = 5014;Errors[110].desc = "The file must be opened as CSV";
|
|
Errors[111].code = 5015;Errors[111].desc = "File reading error";
|
|
Errors[112].code = 5016;Errors[112].desc = "String size must be specified, because the file is opened as binary";
|
|
Errors[113].code = 5017;Errors[113].desc = "A text file must be for string arrays, for other arrays - binary";
|
|
Errors[114].code = 5018;Errors[114].desc = "This is not a file, this is a directory";
|
|
Errors[115].code = 5019;Errors[115].desc = "File does not exist";
|
|
Errors[116].code = 5020;Errors[116].desc = "File can not be rewritten";
|
|
Errors[117].code = 5021;Errors[117].desc = "Wrong directory name";
|
|
Errors[118].code = 5022;Errors[118].desc = "Directory does not exist";
|
|
Errors[119].code = 5023;Errors[119].desc = "This is a file, not a directory";
|
|
Errors[120].code = 5024;Errors[120].desc = "The directory cannot be removed";
|
|
|
|
// String Casting
|
|
Errors[121].code = 5030;Errors[121].desc = "No date in the string";
|
|
Errors[122].code = 5031;Errors[122].desc = "Wrong date in the string";
|
|
Errors[123].code = 5032;Errors[123].desc = "Wrong time in the string";
|
|
Errors[124].code = 5033;Errors[124].desc = "Error converting string to date";
|
|
Errors[125].code = 5034;Errors[125].desc = "Not enough memory for the string";
|
|
Errors[126].code = 5035;Errors[126].desc = "The string length is less than expected";
|
|
Errors[127].code = 5036;Errors[127].desc = "Too large number, more than ULONG_MAX";
|
|
Errors[128].code = 5037;Errors[128].desc = "Invalid format string";
|
|
Errors[129].code = 5038;Errors[129].desc = "Amount of format specifiers more than the parameters";
|
|
Errors[130].code = 5039;Errors[130].desc = "Amount of parameters more than the format specifiers";
|
|
Errors[131].code = 5040;Errors[131].desc = "Damaged parameter of string type";
|
|
Errors[132].code = 5041;Errors[132].desc = "Position outside the string";
|
|
Errors[133].code = 5042;Errors[133].desc = "0 added to the string end, a useless operation";
|
|
Errors[134].code = 5043;Errors[134].desc = "Unknown data type when converting to a string";
|
|
Errors[135].code = 5044;Errors[135].desc = "Damaged string object";
|
|
|
|
// Operations with Arrays
|
|
Errors[136].code = 5050;Errors[136].desc = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only";
|
|
Errors[137].code = 5051;Errors[137].desc = "The receiving array is declared as AS_SERIES, and it is of insufficient size";
|
|
Errors[138].code = 5052;Errors[138].desc = "Too small array, the starting position is outside the array";
|
|
Errors[139].code = 5053;Errors[139].desc = "An array of zero length";
|
|
Errors[140].code = 5054;Errors[140].desc = "Must be a numeric array";
|
|
Errors[141].code = 5055;Errors[141].desc = "Must be a one-dimensional array";
|
|
Errors[142].code = 5056;Errors[142].desc = "Timeseries cannot be used";
|
|
Errors[143].code = 5057;Errors[143].desc = "Must be an array of type double";
|
|
Errors[144].code = 5058;Errors[144].desc = "Must be an array of type float";
|
|
Errors[145].code = 5059;Errors[145].desc = "Must be an array of type long";
|
|
Errors[146].code = 5060;Errors[146].desc = "Must be an array of type int";
|
|
Errors[147].code = 5061;Errors[147].desc = "Must be an array of type short";
|
|
Errors[148].code = 5062;Errors[148].desc = "Must be an array of type char";
|
|
}
|
|
|
|
void ControlErrors::SetAlert(bool value)
|
|
{
|
|
_AlertInfo = value;
|
|
}
|
|
|
|
void ControlErrors::SetPrint(bool value)
|
|
{
|
|
_PrintInfo = value;
|
|
}
|
|
|
|
void ControlErrors::SetSound(bool value)
|
|
{
|
|
_PlaySound = value;
|
|
}
|
|
|
|
void ControlErrors::SetWriteFlag(bool flag)
|
|
{
|
|
_WriteFile = flag;
|
|
}
|
|
|
|
void ControlErrors::SetWritePath(string path)
|
|
{
|
|
_DataPath = path;
|
|
}
|
|
|
|
void ControlErrors::SetPlaySoundFile(string file)
|
|
{
|
|
_PlaySoundFile = file;
|
|
}
|
|
|
|
int ControlErrors::mGetLastError(void)
|
|
{
|
|
_Error.code = GetLastError();
|
|
_Error.desc = mGetDesc(_Error.code);
|
|
return _Error.code;
|
|
}
|
|
|
|
void ControlErrors::mResetLastError(void)
|
|
{
|
|
ResetLastError();
|
|
}
|
|
|
|
int ControlErrors::mGetError(void)
|
|
{
|
|
return _Error.code;
|
|
}
|
|
|
|
void ControlErrors::mResetError(void)
|
|
{
|
|
_Error.code = 0;
|
|
_Error.desc = "";
|
|
}
|
|
|
|
int ControlErrors::mGetTypeError(void)
|
|
{
|
|
if (mGetError() < ERR_USER_ERROR_FIRST)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (mGetError() >= ERR_USER_ERROR_FIRST)
|
|
{
|
|
return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void ControlErrors::mSetUserError(ushort value, string desc = "")
|
|
{
|
|
SetUserError(value);
|
|
_UserError.code = value;
|
|
_UserError.desc = desc;
|
|
}
|
|
|
|
void ControlErrors::mResetUserError(void)
|
|
{
|
|
_UserError.code = 0;
|
|
_UserError.desc = "";
|
|
}
|
|
|
|
string ControlErrors::mGetDesc(int nErr=0)
|
|
{
|
|
int ErrorNumber = 0;
|
|
string ReturnDesc = "";
|
|
|
|
ErrorNumber = (mGetError()>0)?mGetError():ErrorNumber;
|
|
ErrorNumber = (nErr>0)?nErr:ErrorNumber;
|
|
|
|
if ((ErrorNumber > 0) && (ErrorNumber < ERR_USER_ERROR_FIRST))
|
|
{
|
|
for (int i = 0;i<_CountErrors;i++)
|
|
{
|
|
if (Errors[i].code == ErrorNumber)
|
|
{
|
|
ReturnDesc = Errors[i].desc;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (ErrorNumber > ERR_USER_ERROR_FIRST)
|
|
{
|
|
ReturnDesc = (_UserError.desc=="")?"Custom error":_UserError.desc;
|
|
}
|
|
|
|
if (ReturnDesc == ""){return "Unknown error code: "+(string)ErrorNumber;}
|
|
return ReturnDesc;
|
|
}
|
|
|
|
void ControlErrors::mAlert(string message="")
|
|
{
|
|
if (_AlertInfo == true)
|
|
{
|
|
if (message == "")
|
|
{
|
|
if (mGetError() > 0)
|
|
{
|
|
Alert("Error ",mGetError()," - ",mGetDesc());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Alert(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ControlErrors::mPrint(string message="")
|
|
{
|
|
if (_PrintInfo == true)
|
|
{
|
|
if (message == "")
|
|
{
|
|
if (mGetError() > 0)
|
|
{
|
|
Print("Error ",mGetError()," - ",mGetDesc());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ControlErrors::mSound(void)
|
|
{
|
|
if (_PlaySound == true)
|
|
{
|
|
PlaySound(_PlaySoundFile);
|
|
}
|
|
}
|
|
|
|
int ControlErrors::Check(string st="")
|
|
{
|
|
int errNum = 0;
|
|
errNum = mGetLastError();
|
|
mFileWrite();
|
|
mAlert(st);
|
|
mPrint(st);
|
|
mSound();
|
|
mResetError();
|
|
mResetLastError();
|
|
mResetUserError();
|
|
return errNum;
|
|
}
|
|
|
|
int ControlErrors::mFileWrite(string message = "")
|
|
{
|
|
int handle = 0,
|
|
_return = 0;
|
|
datetime time = TimeCurrent();
|
|
string text = (message != "")?message:time+" - Error "+mGetError()+" "+mGetDesc();
|
|
|
|
if (_WriteFile == true)
|
|
{
|
|
handle = FileOpen(_DataPath,FILE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
|
|
if (handle != INVALID_HANDLE)
|
|
{
|
|
ulong size = FileSize(handle);
|
|
FileSeek(handle,size,SEEK_SET);
|
|
_return = FileWrite(handle,text);
|
|
FileClose(handle);
|
|
}
|
|
}
|
|
return _return;
|
|
}
|
|
|
|
|