Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 679
  • Last Modified:

Allow backround events while using URLDownloadToFile API

Hello -
I'm trying to implement an update feature for my program.  Part of that requires launching an Updater.exe file, which in turn downloads the new version of the program I'm trying to update.  To download the new program, I've been using the URLDownloadToFile API. It works, but there are 1-2 problems with it.  

The main one is that once the code executes to download a file using this API, all other events HALT, such that if the file is big, a user may think the Updater is frozen, and indeed it has to be Forced to close until it finishes the download...( For example, moving the form, changing focus, clicking other controls, any event within the form)

I tried using DoEvents, but that doesn't really help, as control passes to the API on that line of code, so I can only allow events before or after the download, but NOT during the download...

One possible solution would be a progress bar such that the end-user can see that its doing something, but thats the second issue.  The ONLY way that I could find that *might* allow showing a progress bar during download is using the pCaller and lpfnCB fields of the API.  But from the looks of it, that only works with a Microsoft ActiveX Control...which this is not, + I would need some help on how to use those.

My goal with this is to make a small, light Updater app that basically downloads a file WITHOUT "freezing" during the download, that shows progress of download.

The download itself would be roughly 260 Kb - 500 Kb, maybe 1-3 times a week.
The main app would check a remote text file, determine if there's an update, if there is launch this updater.exe, which then downloads the new program, kills the current program, and launches the new one.

Any tricks for using this API, or suggestions of better ones appreciated...

  • 4
  • 2
1 Solution
Read up on InternetFileRead, it's much safer and you can actually setup callbacks on this to show progress (it takes a bit of work to use it ASYNC, but it's not impossible).

There are numerous references on the web for this, just search for: "InternetFileRead" "Visual Basic"

You'll get a lot.  I'm using it with some DoEvents to cut down on the non-ASYNC usage, it only pauses during server request/connect (which I also set timeouts for, so even that's not bad).
elmosirisAuthor Commented:
Thanks for that tip... (you must've meant InternetReadFile)... tracked it down, works great, even got it to show a progressbar without callbacks..
Yes, I did.  Silly me, got the name mixed up.  :)  Yes, doing it with InternetREADFile is a breeze.  Plus, you can error check easily as well, know what happened during the transfer, etc.  A lot less "dumbfounded" than URLDownloadToFile.  Glad I could help.
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.


I don't suppose you could share you're findings here???

InternetReadFile is a part of WinInet which is alot more complex than the likes of:

Inet.Protocol = icHTTP
URL = path & filename
FileContents() = Inet.OpenURL(URL, icByteArray)
Taken from the API-Guide for "InternetOpenURL":

Const scUserAgent = "API-Guide test program"
Const sURL = "http://www.microsoft.com/index.htm"
Private Declare Function InternetOpen Lib "wininet" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet" (ByRef hInet As Long) As Long
Private Declare Function InternetReadFile Lib "wininet" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
Private Declare Function InternetOpenUrl Lib "wininet" Alias "InternetOpenUrlA" (ByVal hInternetSession As Long, ByVal lpszUrl As String, ByVal lpszHeaders As String, ByVal dwHeadersLength As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
Private Sub Form_Load()
    'KPD-Team 1999
    'URL: http://www.allapi.net/
    'E-Mail: KPDTeam@Allapi.net

    Dim hOpen As Long, hFile As Long, sBuffer As String, Ret As Long
    'Create a buffer for the file we're going to download
    sBuffer = Space(1000)
    'Create an internet connection
    hOpen = InternetOpen(scUserAgent, INTERNET_OPEN_TYPE_DIRECT, vbNullString, vbNullString, 0)
    'Open the url
    hFile = InternetOpenUrl(hOpen, sURL, vbNullString, ByVal 0&, INTERNET_FLAG_RELOAD, ByVal 0&)
    'Read the first 1000 bytes of the file
    InternetReadFile hFile, sBuffer, 1000, Ret
    'clean up
    InternetCloseHandle hFile
    InternetCloseHandle hOpen
    'Show our file
    MsgBox sBuffer
End Sub

Not sure how this would translate in .net.
Thanks FunkyMeister, now all I need to do is work out how to show the progress.
Well, since the InternetReadFile reads based on available data (if the data ready isn't 1000 as above, it returns what it got instead).

Ret will hold the length of the sBuffer, you can then merely find out using header retrieval, how large the file is first.  Which means, whatever data is present, you get, it doesn't wait for 1000 to come in, it returns what's present in the stream on your end and then returns.  If you want to, you can use the return value from InternetReadFile to see what is happening.  It's 1 while it's going through the file.  There's also getting last dll error to give you information as well.  The Inet errors are betweel 12000 and 13000, that I found.

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now