 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Icarus
Joined: 24 Nov 2005 Posts: 323
|
Posted: Thu Oct 11, 2007 6:37 pm Post subject: UrlDownloadToFile - Timeout and Run In Background |
|
|
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 |
|
 |
Gast w/o Nick Guest
|
Posted: Mon Oct 22, 2007 12:18 pm Post subject: |
|
|
| 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
|
Posted: Fri Oct 26, 2007 2:21 am Post subject: |
|
|
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
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 |
|
 |
Icarus
Joined: 24 Nov 2005 Posts: 323
|
Posted: Fri Oct 26, 2007 1:13 pm Post subject: |
|
|
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 |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10450
|
Posted: Mon Nov 19, 2007 6:23 pm Post subject: |
|
|
| Thanks for the ideas. I'll review this topic again when the time comes to improve UrlDownloadToFile. |
|
| Back to top |
|
 |
DeWild1
Joined: 30 Apr 2006 Posts: 153 Location: Shigle Springs
|
Posted: Tue Nov 20, 2007 1:28 pm Post subject: |
|
|
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..
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.
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..!!
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!  _________________ CPULOCK
virusSWAT
Guaranteed PC
911 PC FIX |
|
| Back to top |
|
 |
gilamar Guest
|
Posted: Tue Apr 22, 2008 3:05 pm Post subject: urldownloadtofile |
|
|
yes if it is possible to have something like:
UrlDownloadToFile, URL, Filename [, Timeout, Wait]
tkanks a lot. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|