Environment: Internet, Networking
This article shows how to create one ATL COM component using the WinInet functions, how to use it in ASP programs, and how to test it from the Visual Basic client. It also shows how to use multithreading support in this component. This component can be used in the same way in Visual Basic, Delphi, Access, or Microsoft SQL.
The article is based on Uwe Keim's article "Calling scripts within scripts"—many thanks to him for his good idea. Of course, you will ask what is new in my component. The reason that made me build this component was the variable time delay at a HTTP request. My solution was an asynchronous retrieve, which gives the user the possibilities to check more often whether the page is completed or not.
The article also contains a Visual Basic client that tests the functionality of the component.
I assume the reader knows or at least has a fair idea about COM programming using ATL.
The component consists of two parts:
- Retrieve method.
Retrieve(BSTR newVal, BSTR *parOut)
- GetPage function.
bool GetPage(CString sURL, CString& sBody)
The Retrieve method just calls the GetPage function with the sURL parameter. Inside the function, there are the calls to WinInet API:
//Open one Internet connection. The //"INTERNET_OPEN_TYPE_PRECONFIG" parameter tells //the function to read the default proxy settings from //the Registry (the proxy settings from connections in IE): HINTERNET internet=InternetOpen("Daemon", INTERNET_OPEN_TYPE_PRECONFIG , NULL, NULL, NULL); //Make one connection with the desired URL. On the third //parameter, we use the "INTERNET_FLAG_RELOAD" while constrains the function not to use a local cached copy. //Take a look at the documentation of this function //to see all the combinations of parameters: HINTERNET file_handle=InternetOpenUrl(internet, sURL, NULL, 0, INTERNET_FLAG_RELOAD, 0); //Read the data from the address: InternetReadFile(file_handle, pagina, 100000, &bytes_read); //Close the connection InternetCloseHandle(internet);The asp source code is very simple (full source code is in the attached file):
url="http://www.codeguru.com" Set myORetrieve = CreateObject("RetrievePage.RetrievePage.1") ret = myORetrieve.Retrieve(url) Response.Write ret
- One asynchronous retrieve module.
- RetrieveAsync method.
RetrieveAsync(BSTR newVal, BSTR *parOut)
- RetrieveAsyncCompleted method.
RetrieveAsyncCompleted(BSTR newVal, BSTR *parOut)
- RetrieveAsyncPage method.
RetrieveAsyncPage(BSTR newVal, BSTR *parOut)
- MyThreadGetPage function.
UINT MyThreadGetPage(LPVOID pParam)
The client must use first the RetrieveAsync method with the desired URL parameter. This method launches one child thread that will retrieve the page in a separate thread. In this way, the program will go to the next instruction and will not wait for the method to finish the request. The program must implement one timer (or at the user's actions) that verifies at some intervals whether the RetrieveAsyncCompleted method returns true (the requested page was retrieved). Only then the RetrieveAsyncPage method will provide the requested page. While the RetrieveAsyncCompleted method returns false, you could send a message such as "Please wait. Data is loading..." to the console.
//Make a new thread. The "MyThreadGetPage" is the name //of the function that will resolve the HTTP request. //Inside the MyThreadGetPage function, there is one call //to the previous discussed GetPage function: AfxBeginThread( MyThreadGetPage , this, THREAD_PRIORITY_NORMAL ) // The program uses a collection to keep all requests to // the component. // Add a new URL request: pObject->m_MapStringToHTTPpage[sKey] = oHTTPpage; // Look at the collection to see whether it is a new URL // or not: m_MapStringToHTTPpage.Lookup(sURL, oHTTPpage)The Visual Basic source code is very simple (full source code is in the attached file, in the RetrieveVBClient director):
'Launch the thread with the specified address str = myORetrieve.RetrieveAsync(URL.Text) 'Look whether the retrieved page is completed: lRetrieveAsyncCompleted = _ myORetrieve.RetrieveAsyncCompleted(URL.Text) 'If it is true, read the data from the specified 'URL address str = myORetrieve.RetrieveAsyncPage(URL.Text)
If you want to see how to build an ATL component, take a look at the "How to Use Crypto API in Your ASP Projects" article.
- RetrieveAsync method.
- Copy the DLL into a directory with system execute privilegess and register it with regsvr32 command or put it on the MTS.
Putting it on the MTS is better because if we want to modify the component and register it again, this is possible without restarting the computer—in case you're using the regsvr32 command that "blocks" your DLL file.
- Use directly the Visual Basic dialog console. Input some string on the URL edit box and click on the button!
- Copy the director with ASP pages on the Web server—and just try it !