AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

UrlDownloadToFile - Timeout and Run In Background

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List
View previous topic :: View next topic  
Author Message
Icarus



Joined: 24 Nov 2005
Posts: 323

PostPosted: Thu Oct 11, 2007 6:37 pm    Post subject: UrlDownloadToFile - Timeout and Run In Background Reply with quote

Ok,

I have read some posts in regards to UrlDownloadToFile, and started some of them.

I hope that UrlDownloadToFile can be improved in some future version.
The two most prominent problems I encounter (and as I noticed in the forum - other people encounter as well) are these:

1. The command is non-interruptable. So, if the web site is not responding fast enough, or if the IE control gets stuck for one reason or another (which happens quite often on more than one of my computers), then the only way is to kill the script's process.

2. The command takes precedence over other threads. For this, I have attached a sample code. See how the updating of the GuiControl is halted when the download is in progress:
Code:

#SingleInstance Force
SetWorkingDir %A_ScriptDir%

Gui Add, Text, w100 vLabel
Gui Show

SetTimer Download, % 5000       ; Download the file every 5 seconds
Gosub Run

Return

Run:
    GuiControl,,Label, %A_TickCount%        ; This update will be halted when
    Sleep 10                                ; download is in progress
    Gosub Run
   
    ;SetTimer Run, -10      ; Using this instead of the above two lines
                            ; improves things a little, but still halting
Return

Download:
    Tooltip Downloading...
    ; Set this to any URL that is downloading slowly on your network
    UrlDownloadToFile, http://www.icq.com/, temp.tmp
    Tooltip
Return

ESC::ExitApp


So, unless there is a solution that I missed in the forums (besides using external DLLs, and RegisterCallback) I would like to suggest additional parameters to UrlDownloadToFile - something like:

Code:

UrlDownloadToFile, URL, Filename [, Timeout, Wait]


Where Timeout is in seconds - if no result, set ErrorLevel.
If "Wait" is used, the next line will not be executed until the file is downloaded, otherwise, the script continues (as SoundPlay)

Also, perhaps there another way to allow other threads to continue working and updating the GUI (as in the above example).

EDIT:
For now, I found the use of RunWait curl.exe -o filename url,,Hide to be the best replacement for UrlDownloadToFile.
Back to top
View user's profile Send private message Visit poster's website
Gast w/o Nick
Guest





PostPosted: Mon Oct 22, 2007 12:18 pm    Post subject: Reply with quote

Quote:
If "Wait" is used, the next line will not be executed until the file is downloaded, otherwise, the script continues (as SoundPlay)


I'd also love this.

To keep it consistent with older scripts, maybe the optional wait command
should be NoWait. Without it, AHK should wait for timeout or the file to finish downloading.
Back to top
tic



Joined: 22 Apr 2007
Posts: 1271

PostPosted: Fri Oct 26, 2007 2:21 am    Post subject: Reply with quote

I agree this should be made as standard, but i believe it can be done with com. Sorry its not integrated all nicely into 1 function, but perhaps you can do it. If not Ill do it another time. I believe the original code is by Olfen:

Code:
Url:= "http://www.autohotkey.com"

CoInitialize()
pWHR := ActiveXObject("WinHttp.WinHttpRequest.5.1") ; CreateObject

SetTimeouts()
sMethod := "GET", Ansi2Unicode(sMethod, wMethod)   
sUrl := Url, Ansi2Unicode(sUrl, wUrl)
DllCall(VTable(pWHR, 9), "Uint", pWHR, "Str", wMethod, "Str", wUrl) ; Open
DllCall(VTable(pWHR, 13), "Uint", pWHR) ; Send

DllCall(VTable(pWHR, 16), "Uint", pWHR, "UIntP", pResponseText) ; ResponseText
Unicode2Ansi(pResponseText, sResponseText)
SysFreeString(pResponseText)
MsgBox, %sResponseText% ; can write this to file (perhaps use binary read/write)

Release(pWHR)
CoUninitialize()
Return


SetTimeouts(Resolve=0, Connect=5000, Send=30000, Receive=5000)
{
   global pWHR
   DllCall(VTable(pWHR, 23), "Uint", pWHR, "Int", Resolve, "Int", Connect, "Int", Send, "Int", Receive)
   Return
}

CoInitialize()
{
   Return   DllCall("ole32\CoInitialize", "Uint", 0)
}

CoUninitialize()
{
   Return   DllCall("ole32\CoUninitialize")
}

SysFreeString(bstr)
{
   Return   DllCall("oleaut32\SysFreeString", "Uint", bstr)
}

VTable(ppv, idx)
{
   Return   NumGet(NumGet(1*ppv)+4*idx)
}

Release(ppv)
{
   Return   DllCall(NumGet(NumGet(1*ppv)+8), "Uint", ppv)
}

Ansi2Unicode(ByRef sString, ByRef wString, nSize = "")
{
   If (nSize = "")
       nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2 + 1)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1)
   Return   &wString
}

Unicode2Ansi(ByRef wString, ByRef sString, nSize = "")
{
   pString := wString + 0 > 65535 ? wString : &wString
   If (nSize = "")
       nSize:=DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "str", sString, "int", nSize + 1, "Uint", 0, "Uint", 0)
   Return   &sString
}

Unicode4Ansi(ByRef wString, sString, nSize = "")
{
   If (nSize = "")
       nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2 + 1)
   DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1)
   Return   &wString
}

ActiveXObject(ProgID)
{
   DllCall("ole32\CoCreateInstance", "Uint", SubStr(ProgID,1,1)="{" ? GUID4String(ProgID,ProgID) : CLSID4ProgID(ProgID,ProgID), "Uint", 0, "Uint", 5, "Uint", GUID4String(IID_IDispatch,"{00020400-0000-0000-C000-000000000046}"), "UintP", pdisp)
   Return   GetDefaultInterface(pdisp)
}

CLSID4ProgID(ByRef CLSID, ProgID, nOffset = 0)
{
   VarSetCapacity(CLSID, 16 + nOffset)
   DllCall("ole32\CLSIDFromProgID", "Uint", Unicode4Ansi(ProgID,ProgID), "Uint", &CLSID + nOffset)
   Return   &CLSID
}

GUID4String(ByRef CLSID, String, nOffset = 0)
{
   VarSetCapacity(CLSID, 16 + nOffset)
   DllCall("ole32\CLSIDFromString", "Uint", Unicode4Ansi(String,String,38), "Uint", &CLSID + nOffset)
   Return   &CLSID
}

GetDefaultInterface(pdisp, LCID = 0)
{
   DllCall(NumGet(NumGet(1*pdisp) +12), "Uint", pdisp , "UintP", ctinf)
   If   ctinf
   {
      DllCall(NumGet(NumGet(1*pdisp)+16), "Uint", pdisp, "Uint" , 0, "Uint", LCID, "UintP", ptinf)
      DllCall(NumGet(NumGet(1*ptinf)+12), "Uint", ptinf, "UintP", pattr)
      DllCall(NumGet(NumGet(1*pdisp)+ 0), "Uint", pdisp, "Uint" , pattr, "UintP", ppv)
      DllCall(NumGet(NumGet(1*ptinf)+76), "Uint", ptinf, "Uint" , pattr)
      DllCall(NumGet(NumGet(1*ptinf)+ 8), "Uint", ptinf)
      If   ppv
      DllCall(NumGet(NumGet(1*pdisp)+ 8), "Uint", pdisp),   pdisp := ppv
   }
   Return   pdisp
}


That will download a url, and has timeouts to connect and download etc
http://msdn2.microsoft.com/en-us/library/aa384061.aspx

and perhaps the standard library could be used to binary read/write?
http://www.autohotkey.com/forum/viewtopic.php?t=19608

Im currently trying to get this to work with multiple threads, but createthread does not seem to want to play nicely with me Crying or Very sad

Edit:
And with your proposal:
Code:
UrlDownloadToFile, URL, Filename [, Timeout, Wait]


I believe extra parameters are needed. Such as timeout to connect and timeout to download, as a host may respond, but might be too slow to retrieve data.
Back to top
View user's profile Send private message
Icarus



Joined: 24 Nov 2005
Posts: 323

PostPosted: Fri Oct 26, 2007 1:13 pm    Post subject: Reply with quote

Hey tic, nice post.

Although it is way too long to my taste, considering the operation at hand is just to download a file, it is good to keep in mind that there are alternatives to the aging UrlDownloadToFile.

I may try it, and perhaps wrap it for easier use (if I do, I will post here).
Back to top
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10450

PostPosted: Mon Nov 19, 2007 6:23 pm    Post subject: Reply with quote

Thanks for the ideas. I'll review this topic again when the time comes to improve UrlDownloadToFile.
Back to top
View user's profile Send private message Send e-mail
DeWild1



Joined: 30 Apr 2006
Posts: 153
Location: Shigle Springs

PostPosted: Tue Nov 20, 2007 1:28 pm    Post subject: Reply with quote

I have had a lot of experience with it.
I have several thousand clients updating my CPULOCK and AntiSpyware program with it.
I first download a small txt with ver # in it, then check the version number of the file on their computer, if they match, nothing, if they don't urldownload then move to replace the file.
Here is a part of my update code.

Code:
;cpulock

filedelete, C:\Program Files\911 PC FIX . COM\utils\update.dat

URLDownloadToFile, http://www.not_public.com/cpulock.txt, C:\Program Files\911 PC FIX . COM\utils\update.dat
sleep, 500
FileRead, return_val, C:\Program Files\911 PC FIX . COM\utils\update.dat
sleep, 500
FileGetVersion, OutputVar, C:\Program Files\911 PC FIX . COM\utils\cpulock.exe
sleep, 500
IfNotEqual, return_val, %OutputVar%
{
URLDownloadToFile, http://www.not_public.com/cpulock.exe, C:\Program Files\911 PC FIX . COM\utils\cpulock2.exe
filedelete, C:\Program Files\911 PC FIX . COM\utils\update.dat
}
else
{
filedelete, C:\Program Files\911 PC FIX . COM\utils\update.dat
}

FileGetSize, size, C:\Program Files\911 PC FIX . COM\utils\cpulock2.exe
IfGreater, size, 1700
{
FileMove, C:\Program Files\911 PC FIX . COM\utils\cpulock2.exe, C:\Program Files\911 PC FIX . COM\utils\cpulock.exe, 1
}

else
{
filedelete, C:\Program Files\911 PC FIX . COM\utils\update.dat
filedelete, C:\Program Files\911 PC FIX . COM\utils\cpulock2.exe
}


Even with the size check, (to make sure it is not just a downloaded error 404 or a partial download, about 1 out of 100 times, there is some strange error.
Sometimes it will download the file, and it will almost be a full size file, but it says exe corrupted.
I think, (I am a very busy guy so I am not 100% sure and just deleted, manually updated, and moved on), that once or twice it would actual run the corrupted EXE but get stuck in a loop on the first part of the compiled script.. Shocked


Not sure how he did it, but, http://noeld.com/programs.asp?cat=misc#download , will use FTP, not just downloading a file, but also compare it, or even directories of files and folders, only downloading new ones.. Very cool. Cool
If I was as smart as Chris, I would find out how he did it in download.exe then duplicate those features in AHK
I am not the only one.. http://www.autohotkey.com/forum/viewtopic.php?p=158796#158796

Something else cool to do with urldownload, data base manipulation..!! Razz Very Happy Cool Wink
AHK code
Code:

DriveGet, serial_num, serial, C:\
UrlDownloadToFile, http://www.not_public.com/someurl.asp?%A_Computername%&%serial_num%&%expire_date%, somefile.tmp
FileDelete, somefile.tmp

On the web server, asp code
Code:

<%
dim str_ini, web_response, arr_ini, comp_name, HD_Serial, expire_date
web_response = "000"
str_ini = request.querystring
if str_ini = "" then
   web_response = "001"
else
   arr_ini = Split(str_ini, "&")
end if

comp_Name = arr_ini(0)
HD_Serial = arr_ini(1)
expire_date = arr_ini(2)

if expire_date = "" then expire_date = "01/01/2060"

if HD_Serial = "" or comp_Name = "" then
   web_response = "001"
else

   '//// CALL DATABASE AND SEE IF SERIAL NUMBER AND COMPUTER NAME EXIST (BOTH MATCHING)

   Set dbConn = Server.CreateObject("ADODB.Connection")
   dbConn.ConnectionString ="PROVIDER=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" & Server.MapPath("some_access_filename.mdb")
   dbConn.open
   set dbRS = server.createObject("ADODB.RecordSet")
   strSQL = "Select * from computer_records WHERE (comp_name = '"& comp_name & "' AND hd_serial = '" & HD_Serial & "')"
   dbRS.open strSQL, dbConn, 2, 3

   if expire_date <> "01/01/2060" then
      expire_date = CStr(Datevalue(expire_date) + 365)
   end if

   if dbRS.eof and dbRS.bof then
      dbRS.addnew
      dbRS("comp_name") = comp_name
      dbRS("hd_serial") = HD_Serial
      dbRS("expire_date") = expire_date

      if Int(now()) > Datevalue(expire_date) then
         dbRS("is_expired") = True
      else
         dbRS("is_expired") = False
      end if
      dbRS.update      
      web_response = "000"
   else
      dbRS.movefirst
      dbRS("expire_date") = expire_date

      if Int(now()) > Datevalue(expire_date) then
         dbRS("is_expired") = True
      else
         dbRS("is_expired") = False
      end if

      dbRS.update
      web_response = "000"
   end if         

   dbRS.close
   dbConn.close
   set dbRS = nothing
   set dbConn = nothing

   response.write(web_response)
end if
%>

Kind of like http://www.autohotkey.com/forum/viewtopic.php?t=5763&highlight=software+protection but a simple access database, I am trying to learn this stuff, but for me it's hard! Twisted Evil
_________________
CPULOCK
virusSWAT
Guaranteed PC
911 PC FIX
Back to top
View user's profile Send private message Visit poster's website
gilamar
Guest





PostPosted: Tue Apr 22, 2008 3:05 pm    Post subject: urldownloadtofile Reply with quote

yes if it is possible to have something like:
UrlDownloadToFile, URL, Filename [, Timeout, Wait]
tkanks a lot.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group