GrabWeb funktioniert nicht auf MT4 Build 600

 

Dieser Code hat für mich einwandfrei funktioniert, bis ich ihn in MT4 build 600 getestet habe, wo er Konten von meinem Server nicht mehr verifiziert.



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:

Dieser Code hat für mich einwandfrei funktioniert, bis ich ihn in MT4 build 600 getestet habe, wo er Konten von meinem Server nicht mehr verifiziert.


Strings werden jetzt im Unicode-Format dargestellt, obwohl sie vorher im ANSI-Format (Einzelbytes) waren. Das sollte berücksichtigt werden, wenn das Programm DLLs verwendet und ihnen String-Variablen übergibt. Beim Aufruf von Windows-API-Funktionen sollten die Unicode-Versionen dieser Funktionen verwendet werden.

Sie müssen Ihren Code anpassen. Verwenden Sie InternetOpenW anstelle von InternetOpenA, dasselbe gilt für andere DLL-Funktionen, die mit 'a' (für ANSI) enden.
 
Vielen Dank für Ihren Vorschlag angevoyageur, aber ich habe versucht, alle ansi 'A' zu W, aber immer noch keine Würfel.
 
thili55:
Vielen Dank für Ihren Vorschlag angevoyageur, aber ich habe versucht, alle ansi 'A' zu W zu wechseln, aber immer noch keine Würfel.

Ihr Problem wird mit InternetReadFile() sein. Siehe EasyXml.mqh auf https://www.mql5.com/en/code/1998 für ein Beispiel, wie man WinInet-Funktionen im neuen MQL4 verwendet - der Code funktioniert sowohl in MQL4 als auch in MQL5.

Im Wesentlichen übergeben Sie ein uchar[]-Array an InternetReadFile() und konvertieren das Array dann mit CharArrayToString() in einen String. In MQL4 können Sie nun verwaltete Speicherpuffer beliebiger Länge zuweisen, sie an eine DLL übergeben und dann die Daten je nach Bedarf in Ansi oder Unicode konvertieren.

 
gchrmt4:

Im Wesentlichen übergeben Sie ein uchar[]-Array an InternetReadFile() und konvertieren das Array dann mit CharArrayToString() in einen String. In MQL4 können Sie nun verwaltete Speicherpuffer beliebiger Länge zuweisen, sie an eine DLL übergeben und dann die Daten je nach Bedarf in Ansi oder Unicode konvertieren.

Um das Thema und die Antwort etwas zu erweitern... in der neuen MQL4 ist es möglich, entweder die A- oder die W-Version vieler Funktionen aufzurufen. Das folgende Skript ruft zum Beispiel das temporäre Windows-Verzeichnis sowohl mit GetTempPathA als auch mit GetTempPathW auf:

#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);
}

Daher ist es möglich, viele Ansi-only DLL-Aufrufe von der neuen MQL4 weiter zu verwenden: Es ist nicht unbedingt notwendig, sowohl den MQL4-Code als auch die DLL zu aktualisieren.

 
gchrmt4:

Daher ist es möglich, viele Ansi-only DLL-Aufrufe von der neuen MQL4 weiter zu verwenden: nicht unbedingt eine Notwendigkeit, sowohl den MQL4-Code und die DLL zu aktualisieren.


... Ein weiteres Beispiel: Übergabe von String-Werten in einen Ansi-DLL-Aufruf aus dem neuen MQL4. (Im wirklichen Leben würden Sie natürlich nur MessageBoxW aufrufen, anstatt diesen Workaround zu verwenden, um MessageBoxA aufzurufen, aber der allgemeine Punkt ist nützlich)

#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);
}
 
Vielen Dank gchrmt4 für die ausführliche Erklärung, leider bin ich nicht viel von einem Programmierer, so dass es nicht scheint, dass ich in der Lage sein, dies selbst zu bewältigen. Ich schaue mir meinen Code und die Beispiele, die Sie gepostet und nicht sicher, was zu tun ist, so sieht es aus wie ich kann jemand finden müssen, dies für mich zu tun.
 
Ich habe jetzt ein paar Stunden damit herumgespielt, aber immer noch kein Glück. Also ja, suchen Sie jemanden zu mieten, dies für mich zu tun ;)
 
thili55:
Ich habe jetzt ein paar Stunden damit herumgespielt, aber immer noch kein Glück. Also ja, suchen Sie jemanden zu mieten, dies für mich zu tun ;)
https://www.mql5.com/en/job
 
thili55:
Ich habe jetzt ein paar Stunden damit herumgespielt, aber immer noch kein Glück. Also ja, suchen Sie jemanden zu mieten, dies für mich zu tun ;)
Siehe https://www.mql5.com/en/forum/149360 - ich wollte das hier als Antwort posten, habe dann aber ein Problem gefunden...
 
gchrmt4:
Siehe https://www.mql5.com/en/forum/149360 - Ich wollte dies als Antwort hier posten, fand dann aber ein Problem...
...Das Skript sollte aber immer noch funktionieren, um kurze Serverantworten wie die Ergebnisse einer Lizenzabfrage abzurufen. Es gibt nur dann Probleme, wenn die Größe der Serverantwort 1 KB überschreitet.