GrabWeb, MT4 Build 600'de çalışmıyor

 

Bu kod, artık sunucumdaki hesapları doğrulamadığı MT4 build 600'de test edene kadar benim için kusursuz çalıştı.



bool bWinInetDebug = false ;

string errorMsg;
 
int hSession_IEType;
int hSession_Direct;
int Internet_Open_Type_Preconfig = 0 ;
int Internet_Open_Type_Direct = 1 ;
int Internet_Open_Type_Proxy = 3 ;
int Buffer_LEN = 250 ;
string answer;

#import "wininet.dll"
 
#define INTERNET_FLAG_PRAGMA_NOCACHE     0x00000100 // Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.
#define INTERNET_FLAG_NO_CACHE_WRITE     0x04000000 // Does not add the returned entity to the cache. 
#define INTERNET_FLAG_RELOAD             0x80000000 // Forces a download of the requested file, object, or directory listing from the origin server, not from the cache.
#define INTERNET_FLAG_KEEP_CONNECTION   0x00400000    // use keep-alive semantics
#define INTERNET_OPEN_TYPE_PRECONFIG                     0    // use registry configuration
#define INTERNET_SERVICE_HTTP   3
#define HTTP_ADDREQ_FLAG_ADD             0x20000000
#define HTTP_ADDREQ_FLAG_REPLACE         0x80000000
int InternetOpenA(
     string      sAgent,
     int         lAccessType,
     string      sProxyName= "" ,
     string      sProxyBypass= "" ,
     int      lFlags= 0
);
 
int InternetOpenUrlA(
     int      hInternetSession,
     string      sUrl, 
     string      sHeaders= "" ,
     int      lHeadersLength= 0 ,
     int      lFlags= 0 ,
     int      lContext= 0 
);
 
int InternetReadFile(
     int      hFile,
     string      sBuffer,
     int      lNumBytesToRead,
     int &     lNumberOfBytesRead[]
);
 
int InternetCloseHandle(
     int      hInet
);

int HttpOpenRequestA(
     int hConnect,
     string lpszVerb,
     string lpszObjectName,
     string lpszVersion,
     string lpszReferrer,
     string lplpszAcceptTypes,
     int   dwFlags,
     int   dwContext);
    
int   InternetOpenA(
     string lpszAgent,
     int dwAccessType,
     string lpszProxy,
     string lpszProxyBypass,
     int dwFlags
    );    
    
int InternetConnectA(
     int hInternet,
     string lpszServerName,
     int nServerPort,
     string lpszUserName,
     string lpszPassword,
     int dwService,
     int dwFlags,
     int dwContext
    );

bool HttpSendRequestA(
     int hRequest,
     string lpszHeaders,
     int dwHeadersLength,
     string lpOptional,
     int dwOptionalLength
    );  
    
bool HttpAddRequestHeadersA(
     int hRequest,
     string lpszHeaders,
     int dwHeadersLength,
     int   dwModifiers
    );          
#import



int logId;
void Log( string st)
{
   if (logId>= 0 )
   {
      
      FileWrite(logId, TimeToStr ( TimeCurrent (), TIME_DATE | TIME_SECONDS ) + ": " + st);
   }
}



int init() 
{ 
GrabWeb( "http://www.website.com/query.php?accountnumber=" + AccountNumber ()+ "&login=" +User, answer);
}



int hSession( bool Direct)
{
     string InternetAgent;
     if (hSession_IEType == 0 )
    {
        InternetAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)" ;
        hSession_IEType = InternetOpenA(InternetAgent, Internet_Open_Type_Preconfig, "0" , "0" , 0 );
        hSession_Direct = InternetOpenA(InternetAgent, Internet_Open_Type_Direct, "0" , "0" , 0 );
    }
     if (Direct) 
    { 
         return (hSession_Direct); 
    }
     else 
    {
         return (hSession_IEType); 
    }
}

bool GrabWeb( string strUrl, string & strWebPage)
{
     int      hInternet;
     int         iResult;
     int      lReturn[]={ 1 };
     string      sBuffer= "x" ;
     int      bytes;
    
    hInternet = InternetOpenUrlA(hSession( FALSE ), strUrl, "0" , 0 , 
                                INTERNET_FLAG_NO_CACHE_WRITE | 
                                INTERNET_FLAG_PRAGMA_NOCACHE | 
                                INTERNET_FLAG_RELOAD, 0 );
                                
 
     if (hInternet == 0 ) 
         return ( false );
         
    iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);     

     if (iResult == 0 ) 
         return ( false );
    bytes = lReturn[ 0 ];

    strWebPage = StringSubstr (sBuffer, 0 , lReturn[ 0 ]);    
     // If there's more data then keep reading it into the buffer
     while (lReturn[ 0 ] != 0 )
    {
        iResult = InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn);
         if (lReturn[ 0 ]== 0 ) 
             break ;
        bytes = bytes + lReturn[ 0 ];
       
        strWebPage = strWebPage + StringSubstr (sBuffer, 0 , lReturn[ 0 ]);
    }
    
  
   
      
    iResult = InternetCloseHandle(hInternet);
     if (iResult == 0 ) 
         return ( false );
   
     return ( true );
}

int deinit() {
   FileClose (logId);
   return ( 0 );
}
 
thili55 :

Bu kod, artık sunucumdaki hesapları doğrulamadığı MT4 build 600'de test edene kadar benim için kusursuz çalıştı.


Daha önce ANSI biçiminde (tek baytlılar) olmalarına rağmen, dizeler artık Unicode biçiminde sunulmaktadır. Program DLL'leri kullanıyorsa ve bunlara dize değişkenleri iletiyorsa, bu dikkate alınmalıdır. Windows API işlevleri çağrılırken bu işlevlerin Unicode sürümleri kullanılmalıdır.

Kodunuzu uyarlamanız gerekir. InternetOpenA yerine InternetOpenW kullanın, 'a' (ANSI için) ile sonlandırılan diğer DLL işlevleri için aynı.
 
Öneriniz için teşekkürler, ama tüm ansi 'A'yı W'ye çevirmeyi denedim ama yine de zar yok.
 
thili55 :
Öneriniz için teşekkürler, ama tüm ansi 'A'yı W'ye çevirmeye çalıştım ama yine de zar yok.

Sorununuz InternetReadFile() ile olacak. Yeni MQL4'te WinInet işlevlerinin nasıl kullanılacağına ilişkin bir örnek için https://www.mql5.com/en/code/1998 adresindeki EasyXml.mqh adresine bakın - kod hem MQL4 hem de MQL5'te çalışır.

Özünde, bir uchar[] dizisini InternetReadFile() öğesine iletirsiniz ve ardından diziyi CharArrayToString() kullanarak bir dizeye dönüştürürsünüz. Şimdi MQL4'te yapabileceğiniz şey, yönetilen bellek arabelleklerini keyfi uzunlukta tahsis etmek, bunları bir DLL'ye geçirmek ve ardından verileri uygun şekilde Ansi veya Unicode'dan dönüştürmektir.

 
gchrmt4 :

Özünde, bir uchar[] dizisini InternetReadFile() öğesine iletirsiniz ve ardından diziyi CharArrayToString() kullanarak bir dizeye dönüştürürsünüz. Şimdi MQL4'te yapabileceğiniz şey, yönetilen bellek arabelleklerini keyfi uzunlukta tahsis etmek, bunları bir DLL'ye geçirmek ve ardından verileri uygun şekilde Ansi veya Unicode'dan dönüştürmektir.

Konuyu genişleterek ve biraz cevap vererek... yeni MQL4'te birçok işlevin A veya W sürümlerini çağırmak mümkündür. Örneğin, aşağıdaki komut dosyası hem GetTempPathA hem de GetTempPathW çağrılarını kullanarak Windows geçici dizinini alır:

 #import "kernel32.dll"
   int GetTempPathA( int , uchar & arr[]);
   int GetTempPathW( int , short & arr[]);
#import

void OnStart ()
{
   uchar AnsiStringBuffer[ 256 ];
   GetTempPathA( 255 , AnsiStringBuffer);
   string strTempPathFromA = CharArrayToString (AnsiStringBuffer);

   short UnicodeStringBuffer[ 256 ];
   GetTempPathW( 255 , UnicodeStringBuffer);
   string strTempPathFromW = ShortArrayToString (UnicodeStringBuffer);

   Print ( "Temp path via GetTempPathA(): " , strTempPathFromA);
   Print ( "Temp path via GetTempPathW(): " , strTempPathFromW);
}

Bu nedenle, yeni MQL4'ten birçok yalnızca Ansi DLL çağrısını kullanmaya devam etmek mümkündür: MQL4 kodunu ve DLL'yi güncellemeniz gerekmez.

 
gchrmt4 :

Bu nedenle, yeni MQL4'ten birçok yalnızca Ansi DLL çağrısını kullanmaya devam etmek mümkündür: MQL4 kodunu ve DLL'yi güncellemeniz gerekmez.


... Başka bir örnek: dize değerlerini yeni MQL4'ten bir Ansi DLL çağrısına geçirmek. (Gerçek hayatta, MessageBoxA'yı aramak için bu geçici çözümü kullanmak yerine açıkça MessageBoxW'yi çağırırsınız, ancak genel nokta yararlıdır)

 #import "user32.dll"
   // Declare the Ansi function as taking uchar[] input parameters instead of strings
   int MessageBoxA( int , uchar & arr1[], uchar & arr2[], int );
#import

void OnStart ()
{
   string strMessage = "Hello" ;
   string strTitle = "Hi!" ;
   
   // Convert the strings to uchar[] arrays
   uchar ucMessage[], ucTitle[];
   StringToCharArray (strMessage, ucMessage);
   StringToCharArray (strTitle, ucTitle);
   
   MessageBoxA( 0 , ucMessage, ucTitle, 64 );
}
 
Ayrıntılı açıklama için teşekkürler gchrmt4, ne yazık ki pek programcı değilim, bu yüzden bunu kendim halledebileceğim görünmüyor. Koduma ve gönderdiğiniz örneklere bakıyorum ve ne yapacağımdan emin değilim, bu yüzden bunu benim için yapacak birini bulmam gerekebilir gibi görünüyor.
 
Birkaç saattir bununla uğraşıyorum, hala şans yok. Yani evet, bunu benim için yapacak birini işe almak istiyorum;)
 
thili55 :
Birkaç saattir bununla uğraşıyorum, hala şans yok. Yani evet, bunu benim için yapacak birini işe almak istiyorum;)
https://www.mql5.com/en/job
 
thili55 :
Birkaç saattir bununla uğraşıyorum, hala şans yok. Yani evet, bunu benim için yapacak birini arıyorum ;)
Bakın https://www.mql5.com/en/forum/149360 - Bunu buraya cevap olarak göndermek üzereydim ama sonra bir sorun buldum ...
 
gchrmt4 :
Bakın https://www.mql5.com/en/forum/149360 - Bunu buraya cevap olarak göndermek üzereydim ama sonra bir sorun buldum ...
...Ancak, bu komut dosyası, bir lisans sorgusunun sonuçları gibi kısa sunucu yanıtlarını almak için yine de çalışmalıdır. Yalnızca sunucunun yanıtının boyutu 1KB-ish'i aşarsa sorunları olur.
Neden: