Hi, I try to translate the following XMLHTTP code by using Jose's WinFBX include files ie AfxCom syntax, but the FB 1.07.1 Win32 Compiler throws me an error. I'm probably not assigning interface pointers correctly. Have studied the Sapi example in depth though.
This is the Disphelper XLMHTTP code that I try to convert.
'' HTTP GET example, using MSXML2
#define UNICODE
#include "disphelper/disphelper.bi"
DISPATCH_OBJ(objHTTP)
dhInitialize(TRUE)
dhToggleExceptions(TRUE)
dhCreateObject("MSXML2.XMLHTTP.4.0", NULL, @objHTTP)
dhCallMethod(objHTTP, ".Open(%s, %s, %b)", "GET", "http://sourceforge.net", FALSE)
dhCallMethod(objHTTP, ".Send")
Dim As ZString Ptr szResponse
dhGetValue("%s", @szResponse, objHTTP, ".ResponseText")
Print "Response: "; *szResponse
dhFreeString(szResponse)
SAFE_RELEASE(objHTTP)
dhUninitialize(TRUE)
Here's my translated code that doesn't work
#pragma once
#include once "Afx/AfxSpError.bi"
#include once "Afx/AfxCOM.inc"
using Afx
NAMESPACE Afx
'' // The definition for BSTR in the FreeBASIC headers was inconveniently changed to WCHAR
#ifndef AFX_BSTR
#define AFX_BSTR WSTRING PTR
#endif
'----------------------------Start Copy------------------------------------
'Excerpts copied from msxlm3.dll TypeLib via Jose's TypeLib Browser for Freebasic
CONST AFX_PROGID_Msxml2_XMLHTTP = "Msxml2.XMLHTTP"
CONST AFX_CLSID_XMLHTTP = "{F6D90F16-9C73-11D3-B32E-00C04F990BB4}"
CONST AFX_IID_IXMLHTTPRequest = "{ED8C108D-4349-11D2-91A4-00C04F7969E8}"
TYPE Afx_IXMLHTTPRequest AS IXMLHTTPRequest_
TYPE IXMLHTTPRequest_ EXTENDS Afx_iDispatch
DECLARE ABSTRACT FUNCTION open (BYVAL bstrMethod AS BSTR, BYVAL bstrUrl AS BSTR, BYVAL varAsync AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND), BYVAL bstrUser AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND), BYVAL bstrPassword AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND)) AS HRESULT
DECLARE ABSTRACT FUNCTION setRequestHeader (BYVAL bstrHeader AS BSTR, BYVAL bstrValue AS BSTR) AS HRESULT
DECLARE ABSTRACT FUNCTION getResponseHeader (BYVAL bstrHeader AS BSTR, BYVAL pbstrValue AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION getAllResponseHeaders (BYVAL pbstrHeaders AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION send (BYVAL varBody AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND)) AS HRESULT
DECLARE ABSTRACT FUNCTION abort () AS HRESULT
DECLARE ABSTRACT FUNCTION get_status (BYVAL plStatus AS LONG PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_statusText (BYVAL pbstrStatus AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseXML (BYVAL ppBody AS IDispatch PTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseText (BYVAL pbstrBody AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseBody (BYVAL pvarBody AS VARIANT PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseStream (BYVAL pvarBody AS VARIANT PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_readyState (BYVAL plState AS LONG PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION put_onreadystatechange (BYVAL rhs AS IDispatch PTR) AS HRESULT
END TYPE
end namespace
'--------------------------End Copy-----------------------------------------------
' // Initialize the COM library
CoInitialize(NULL)
dim pXlm AS Afx_IXMLHTTPRequest PTR = AfxNewCom(AFX_PROGID_Msxml2_XMLHTTP )
' // Create an instance of the MSXLM object
IF pXlm THEN print "yes"
'Get compiler error: error 18: Element not defined, open in 'pXlm->open("GET","http://sourceforge.net" ,false)'
pXlm->open("GET","http://sourceforge.net" ,false)
' // Uninitalize COM
CoUninitialize
sleep
Any hints?
Eigil
Be careful with old examples because they may try to use COM servers that are obsolete or not installed in your computer. The latest version that I have installed is the 6.0, so I have changed the code accordingly. You have generated identifiers for version 3.0, that does not work in my computer. Also note that the valid url is no longer "http://sourceforge.net/", but "https://sourceforge.net/".
'#CONSOLE ON
#include once "Afx/AfxCOM.inc"
using Afx
'----------------------------Start Copy------------------------------------
'Excerpts copied from msxlm3.dll TypeLib via Jose's TypeLib Browser for Freebasic
' CONST AFX_PROGID_Msxml2_XMLHTTP = "Msxml2.XMLHTTP"
' CONST AFX_CLSID_XMLHTTP = "{F6D90F16-9C73-11D3-B32E-00C04F990BB4}"
CONST AFX_PROGID_Msxml2_XMLHTTP_6_0 = "Msxml2.XMLHTTP.6.0"
CONST AFX_CLSID_XMLHTTP60 = "{88D96A0A-F192-11D4-A65F-0040963251E5}"
CONST AFX_IID_IXMLHTTPRequest = "{ED8C108D-4349-11D2-91A4-00C04F7969E8}"
TYPE Afx_IXMLHTTPRequest AS Afx_IXMLHTTPRequest_
TYPE Afx_IXMLHTTPRequest_ EXTENDS Afx_iDispatch
DECLARE ABSTRACT FUNCTION open (BYVAL bstrMethod AS BSTR, BYVAL bstrUrl AS BSTR, BYVAL varAsync AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND), BYVAL bstrUser AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND), BYVAL bstrPassword AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND)) AS HRESULT
DECLARE ABSTRACT FUNCTION setRequestHeader (BYVAL bstrHeader AS BSTR, BYVAL bstrValue AS BSTR) AS HRESULT
DECLARE ABSTRACT FUNCTION getResponseHeader (BYVAL bstrHeader AS BSTR, BYVAL pbstrValue AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION getAllResponseHeaders (BYVAL pbstrHeaders AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION send (BYVAL varBody AS VARIANT = TYPE(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND)) AS HRESULT
DECLARE ABSTRACT FUNCTION abort () AS HRESULT
DECLARE ABSTRACT FUNCTION get_status (BYVAL plStatus AS LONG PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_statusText (BYVAL pbstrStatus AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseXML (BYVAL ppBody AS IDispatch PTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseText (BYVAL pbstrBody AS BSTR PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseBody (BYVAL pvarBody AS VARIANT PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_responseStream (BYVAL pvarBody AS VARIANT PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION get_readyState (BYVAL plState AS LONG PTR) AS HRESULT
DECLARE ABSTRACT FUNCTION put_onreadystatechange (BYVAL rhs AS IDispatch PTR) AS HRESULT
END TYPE
'--------------------------End Copy-----------------------------------------------
' // Initialize the COM library
CoInitialize(NULL)
dim pXlm AS Afx_IXMLHTTPRequest PTR = AfxNewCom(AFX_PROGID_Msxml2_XMLHTTP_6_0)
' // Create an instance of the MSXLM object
IF pXlm THEN print "yes"
DIM cbsMethod AS CBSTR = "GET"
DIM cbsUrl AS CBSTR = "https://sourceforge.net/"
DIM varAsync AS VARIANT = TYPE(VT_BOOL,0,0,0,0)
DIM hr AS HRESULT = pXlm->open(cbsMethod, cbsUrl, varAsync)
hr = pXlm->Send
DIM cwsResponse AS CBSTR
hr = pXlm->get_responseText(cwsResponse.vptr)
print cwsResponse
' // Release the interface
AfxSafeRelease(pXlm)
' // Uninitalize COM
CoUninitialize
sleep
PS. I have added Afx_ to IXMLHTTPRequest_ because, otherwise, it conflicts with the declaration in the FB headers. Will change my TypeLib Browser to always add the Afx_ prefix.
Many thanks for answer Josè.
It is somewhat comforting that I was on right track, but worked on «obsolete» code framework.
Eigil
Alternate way using the CDispInvoke class:
'#CONSOLE ON
#include once "Afx/CDIspInvoke.inc"
using Afx
' // Create an instance of the Msxml2 object
DIM pDisp AS CDispInvoke = "Msxml2.XMLHTTP.6.0"
' // To check for success, see if the value returned by the DispPtr method is not null
IF pDisp.DispPtr = NULL THEN END
pDisp.Invoke("open", "GET", "https://sourceforge.net/", 0)
pDisp.Invoke("Send")
DIM strResponse AS STRING = pDisp.Get("ResponseText")
print strResponse
SLEEP
Similar to dispHelper, but easier and without the need to use an external DLL. And it works with both 32 and 64 bit.
Thank you again Josè,
Think I'll proceed with the CDispinvoke class. Less code and less verbose than my initial approach. The XMLHTTP communication is just a small part of my code.
Eigil