Click here to Skip to main content
Click here to Skip to main content

Using WinInet to Call a Server Script Asynchronously

By , 24 Aug 2007
 

Introduction

I wanted to find a simple way of running a script (e.g. Perl, PHP, etc.) on a webserver but it needed to be asynchronous as I didn't want the application to hang while waiting for the webserver's response. I didn't need to read any output from the script so all the solutions I could find were overly complicated for my needs.

Theory

  1. Use INTERNET_FLAG_ASYNC to open the session
  2. Set a status callback using InternetSetStatusCallback
  3. Open the connection using InternetOpenUrl
  4. Read the handle when the callback function receives INTERNET_STATUS_HANDLE_CREATED
  5. Free up everything when the call has finished and the callback function receives INTERNET_STATUS_REQUEST_COMPLETE

Using the Code

The complete code is:

HINTERNET    hInternetSession = NULL;   
HINTERNET    hURL = NULL;

typedef struct
{
    HWND        hWindow;     // window handle
    HINTERNET   hResource;   // HINTERNET handle created by InternetOpenUrl
} REQUEST_CONTEXT;

REQUEST_CONTEXT    request_context;

void __stdcall InternetCallbackFunction(HINTERNET hInternet,
                        DWORD dwContext,
                        DWORD dwInternetStatus,
                        LPVOID lpvStatusInformation,
                        DWORD dwStatusInformationLength)
{
    REQUEST_CONTEXT* cpContext;
    INTERNET_ASYNC_RESULT* res;

    cpContext = (REQUEST_CONTEXT*)dwContext;

    // what has this callback function been told has happened?
    switch (dwInternetStatus)
    {
        case INTERNET_STATUS_HANDLE_CREATED:
            // get the handle now that it has been created so it can be freed up later
            res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
            hURL = (HINTERNET)(res->dwResult);

            break;

        case INTERNET_STATUS_REQUEST_COMPLETE:
            // script has been called so close handles now and 
	   // cancel the callback function
            InternetCloseHandle(hURL);
            InternetSetStatusCallback(hInternetSession, NULL);
            InternetCloseHandle(hInternetSession);

            // flag as having been completed now
            hURL = NULL;
            hInternetSession = NULL;

            break;
    }
}

void RunScript(char* szURL)
{
    // only run this script if finished all others
    if (hInternetSession == NULL)
    {
        hInternetSession = InternetOpen("Microsoft Internet Explorer",
                        INTERNET_OPEN_TYPE_PRECONFIG,
                        NULL,
                        NULL,
                        INTERNET_FLAG_ASYNC);
        
        if (hInternetSession != NULL)
        {
            // set the callback function
            InternetSetStatusCallback(hInternetSession,
                        (INTERNET_STATUS_CALLBACK)InternetCallbackFunction);

            // run the script
            hURL = InternetOpenUrl(hInternetSession,
                        szURL,
                        NULL,
                        0,
                        INTERNET_FLAG_RELOAD |
                        INTERNET_FLAG_PRAGMA_NOCACHE |
                        INTERNET_FLAG_NO_CACHE_WRITE,
                        (unsigned long)(&request_context));
        }
    }
}   

History

  • 24th August, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sean OConnor
Web Developer
United Kingdom United Kingdom
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
General997 errormemberdelinhabit6 May '08 - 2:05 
I implemented your code in my application and i'm getting an 997 error code (GetLastError) after calling InternetOpenUrl. I want to implement a progress bar to see the download progress.
 
Have you encountered this behavior?
Thanks!
GeneralRe: 997 error PinmemberShilpi Boosar18 May '08 - 21:15 
Hi Yes i am also facing the same problem.Did you got any solution for the problem ?? Smile | :)
 
Yes U Can ...If U Can ,Dream it , U can do it ...ICAN

GeneralRe: 997 error Pinmemberdelinhabit18 May '08 - 23:49 
I was reading data from the internet file and there was my problem. I was trying to read while my connection was pending. I did an asynchronous read and solved the problem. This example does not read any data and it's working perfectly.
GeneralRe: 997 error PinmemberShilpi Boosar18 May '08 - 23:59 
I am also trying to read data but the main issue is that internetOpenurl handle is null and an error message 997 occur.
Can you please send me your code for the same just to cross check what is my mistake?? Smile | :)
thanks in advance
 
Yes U Can ...If U Can ,Dream it , U can do it ...ICAN

GeneralRe: 997 error Pinmemberdelinhabit19 May '08 - 0:18 
Sadly I couldn't find any solutions to my problem using asynchronous calls. I used synchronous calls on separate thread to do the job. It seems that internet asynchronous calls aren't fully supported in MFC.
Try this article, it helped me to solve my problem:
http://www.codeguru.com/Cpp/I-N/internet/filetransfer/article.php/c6235[^]
Good luck!
GeneralRe: 997 error PinmemberShilpi Boosar19 May '08 - 0:42 
Oh !
actually i created a suggestion list using syncronous connection and thread and it is working fine but the issue is its efficiency and for this i am using asyncronous connetion but i dont find much about asyncronous connnetion article Frown | :( .Thanks for your reply Smile | :)
 
Yes U Can ...If U Can ,Dream it , U can do it ...ICAN

GeneralRe: 997 error Pinmemberdelinhabit19 May '08 - 0:55 
You're welcome!
What do you mean by inefficiency?
If you are saying that using a worker thread for synchronous calls lacks efficiency, you may be wrong.
I think that asynchronous calls use their own threads created transparently by MFC. I think the synchronous + worker thread solution isn't less efficient than the asynchronous one.
 
----------------------------------------------------
I do believe in monsters, I call them officers....
GeneralRe: 997 error PinmemberShilpi Boosar19 May '08 - 1:36 
Actually i am working on generating a suggestion list . When i write in english the same is phonetically converted into hindi or other indian langugaes and give the appropriate suggestion to me.
and i do not want user to wait for response so i use thread to send request and use syncronous connecion to get response and i use one condition if current buffer is same as response buffer than only the suggestion is display.It is done and working properly, but when i type very fast than it takes time for me to display suggestion list when i stop typing.
and this is because it wait for response. that's the reason i switch to asyncronous connection. Smile | :)
I think now i am clear.
 
Yes U Can ...If U Can ,Dream it , U can do it ...ICAN

GeneralRe: 997 error PinmemberAnandtv28 May '08 - 2:31 
Error 997 is ERROR_IO_PENDING and is a proper return value for the asynchronous call that you made. It just says that IO is happening asynchronously in the background and may complete at a later time.
The completion/failure is notified in the Status Call back function.
GeneralRe: 997 error PinmemberShilpi Boosar28 May '08 - 2:57 
Yes i read it somewhere that if this error appear in asyncronous connection than ignore that. But i face a new problem for one request StatusCallback Function creates one or more handle.I dont know how to tackle it Frown | :(
 
Yes U Can ...If U Can ,Dream it , U can do it ...ICAN

AnswerRe: 997 error PinmemberAnandtv28 May '08 - 20:04 
It depends on what WinInet API you are calling.
 
If you are directly calling InternetOpenUrl, then there will only be one handle provided in the callback, which is the handle to the resource.
 
However if you are calling InternetConnect, HttpOpenRequest and HttpSendRequest, then there will 2 handles provided in the callback, of which the first one will be the handle to the connection and the second one will be the handle to the resource.
 
I have developed a sample async WinInet client in this order.
1. Read the CodeProject article
CodeProject: Using WinInet HTTP functions in Full Asynchronous Mode. Free source code and programming help
 
2. Copied the Async WinInet sample code from MSDN
Asynchronous WinInet Example
 
3. Modified the sample as below.
- Replaced InternetReadFile(synchronous) with InternetReadFileEx(asynchronous) and also adjusted the parameters.
- Removed the code to create a thread to do the reading since the Read call is now asynchronous.
GeneralRe: 997 error PinmemberShilpi Boosar28 May '08 - 20:44 
I am working for the same URL that you give to me and i am using InternetOpenURL but InternetCallbackFunction calls INTERNET_STATUS_HANDLE_CREATED twice or trice and if in between
INTERNET_STATUS_REQUEST_COMPLETE calls than crash occur Frown | :(
If possible than please send me your code so that i check what was wrong.
Thanks for your reply Smile | :)
 
Yes U Can ...If U Can ,Dream it , U can do it ...ICAN

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 24 Aug 2007
Article Copyright 2007 by Sean OConnor
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid