GrabWeb이 MT4 Build 600에서 작동하지 않음

 

이 코드는 더 이상 내 서버의 계정을 확인하지 않는 MT4 빌드 600에서 테스트할 때까지 완벽하게 작동했습니다.



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 :

이 코드는 더 이상 내 서버의 계정을 확인하지 않는 MT4 빌드 600에서 테스트할 때까지 완벽하게 작동했습니다.


문자열은 이전에는 ANSI 형식(단일 바이트 형식)이었지만 이제 유니코드 형식으로 표시됩니다. 프로그램이 DLL을 사용하고 문자열 변수를 DLL에 전달하는 경우 이를 고려해야 합니다. Windows API 함수를 호출할 때 이러한 함수의 유니코드 버전을 사용해야 합니다.

코드를 수정해야 합니다. 'a'(ANSI의 경우)로 종료되는 다른 DLL 함수 와 동일하게 InternetOpenA 대신 InternetOpenW를 사용하십시오.
 
gevoyageur 제안해주셔서 감사합니다. 하지만 모든 si 'A'를 W로 전환하려고 했지만 여전히 주사위가 없습니다.
 
thili55 :
gevoyageur 제안해주셔서 감사합니다. 하지만 모든 si 'A'를 W로 전환하려고 했지만 여전히 주사위가 없습니다.

문제는 InternetReadFile()에 있을 것입니다. 새 MQL4에서 WinInet 기능을 사용하는 방법에 대한 예는 https://www.mql5.com/en/code/1998 에서 EasyXml.mqh를 참조하십시오. 코드는 MQL4와 MQL5에서 모두 작동합니다.

본질적으로 uchar[] 배열을 InternetReadFile()에 전달한 다음 CharArrayToString()을 사용하여 배열을 문자열로 변환합니다. 이제 MQL4에서 할 수 있는 일은 임의 길이의 관리되는 메모리 버퍼를 할당하고 DLL에 전달한 다음 해당하는 경우 Ansi 또는 유니코드의 데이터를 변환하는 것입니다.

 
gchrmt4 :

본질적으로 uchar[] 배열을 InternetReadFile()에 전달한 다음 CharArrayToString()을 사용하여 배열을 문자열로 변환합니다. 이제 MQL4에서 할 수 있는 일은 임의 길이의 관리되는 메모리 버퍼를 할당하고 DLL에 전달한 다음 해당하는 경우 Ansi 또는 유니코드의 데이터를 변환하는 것입니다.

주제와 답변을 약간 확장하면... 새로운 MQL4에서는 많은 기능 의 A 또는 W 버전을 호출할 수 있습니다. 예를 들어 다음 스크립트는 GetTempPathA 및 GetTempPathW 호출을 모두 사용하여 Windows 임시 디렉터리를 가져옵니다.

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

따라서 새로운 MQL4에서 많은 Ansi 전용 DLL 호출을 계속 사용할 수 있습니다. MQL4 코드 DLL을 모두 업데이트할 필요는 없습니다.

 
gchrmt4 :

따라서 새로운 MQL4에서 많은 Ansi 전용 DLL 호출을 계속 사용할 수 있습니다. MQL4 코드 DLL을 모두 업데이트할 필요는 없습니다.


... 또 다른 예: 새 MQL4에서 Ansi DLL 호출 문자열 값 전달. (실생활에서는 분명히 이 해결 방법을 사용하여 MessageBoxA 를 호출하는 대신 MessageBoxW를 호출하지만 일반적인 요점은 유용합니다.)

 #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 );
}
 
자세한 설명에 대해 gchrmt4에게 감사드립니다. 불행히도 저는 프로그래머가 아니기 때문에 이 문제를 직접 해결할 수 있을 것 같지는 않습니다. 제 코드와 귀하가 게시한 예제를 보고 있는데 어떻게 해야 할지 잘 모르겠어서 저를 대신해 이 작업을 수행할 사람을 찾아야 할 것 같습니다.
 
나는 지금 몇 시간 동안 이것을 가지고 놀았지만 여전히 운이 없습니다. 예, 저를 위해 이 일을 할 사람을 고용하려고 합니다 ;)
 
thili55 :
나는 지금 몇 시간 동안 이것을 가지고 놀았지만 여전히 운이 없습니다. 예, 저를 위해 이 일을 할 사람을 고용하려고 합니다 ;)
https://www.mql5.com/en/job
 
thili55 :
나는 지금 몇 시간 동안 이것을 가지고 놀았지만 여전히 운이 없습니다. 예, 저를 위해 이 일을 할 사람을 고용하려고 합니다 ;)
https://www.mql5.com/en/forum/149360 참조 - 여기에 답변으로 게시하려고 했지만 문제가 발견되었습니다...
 
gchrmt4 :
https://www.mql5.com/en/forum/149360 참조 - 여기에 답변으로 게시하려고 했으나 문제가 발견되었습니다...
...그러나 해당 스크립트는 라이선스 쿼리 결과와 같은 짧은 서버 응답을 검색하는 데 계속 작동해야 합니다. 서버 응답의 크기가 1KB-ish를 초과하는 경우에만 문제가 있습니다.
사유: