Jump to content
JoeBar

IE Click a button to DL

Recommended Posts

Hi, im' trying to automate downloading of files on a NAS. My Gui will open a hidden IE window, then naviguate and download a .zip file.

I manage to click on some buttons, and the last one ("Ok") creates a .zip of current folder and directly pops a window to download the file.

So the file is automatically generated when the user click on the "Ok" button.

 

I would want the entire process to be hidden; when the download request happens, my program accepts it (doesn't know how to do) and after that,  my program pops a SaveFile window to the user (so this Window will not be hidden). After that, the file is downloaded according to the SaveFile.

 

For information, the url of the file is fixed but this file is generated on the fly and the access disappears after that, so i can't download it directly as usual with InetGet ("webservernas/download/webapi/file_download.cgi/file.zip").

Here is my script :

Local $oIE = _IECreate('webservernas/download/fedggd31/Folder1')
    If @error Then
        MsgBox($MB_ICONERROR, '_IECreate', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(1,0,0)
    Endif
    Sleep(1000)
    
    Local $oBouttonDL = _IEGetObjById($oIE, 'ext-gen76')
    If @error Then
        MsgBox($MB_ICONERROR, '_IEGetObjById1', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(2,0,0)
    Endif
    _IEAction($oBouttonDL, 'click')

    Local $oBouttonOK = _IEGetObjById($oIE, 'ext-gen174')
       If @error Then
        MsgBox($MB_ICONERROR, '_IEGetObjById2', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(2,0,0)
    Endif
    _IEAction($oBouttonOK, 'click')
    Sleep(1000)

For the tests, i've not hidden the window, i will make it after all is well tested.

Thanks.

Edited by JoeBar

Share this post


Link to post
Share on other sites

I found here a method to send clicks on the Save As windows to achieve the download :

$hIE = WinGetHandle("[Class:IEFrame]")
$hCtrl = ControlGetHandle($hIE,"","[Class:DirectUIHWND]")
$aPos = ControlGetPos($hIE,"",$hCtrl)
$x = $aPos[2]-160
$y = $aPos[3]-30

WinActivate($hIE) ; doesn't work in the background
ControlClick($hIE,"",$hCtrl,"primary",1,$x,$y) ; this only gives focus to the save button
ControlSend($hIE,"",$hCtrl,"{down}") ; this does work once the save button is focussed
ControlSend($hie, "", "[Class:DirectUIHWND]","s")

; save as - Dont need to change any of this except for filepath.
WinActivate("Enregistrer sous", "Enregistrer");
WinWaitActive("Enregistrer sous", "Enregistrer", 10);
ControlSetText("Enregistrer sous", "", "Edit1", @DesktopDir)
ControlClick("Enregistrer sous", "", "&Enregistrer", "left", 1, 5, 5)

The only problem is that it needs to WinActivate, which make the window lose his hidden state.

It's working in fact, IE remains hidden and just the Save As windows is opening and is visible for the user.

Fine !

Edited by JoeBar

Share this post


Link to post
Share on other sites

So, the buttons and download themselves are working, i would just ask if in the code of my 1st post, i could avoid to put the Sleep(1000) :

Local $oIE = _IECreate('webservernas/download/fedggd31/Folder1')
    If @error Then
        MsgBox($MB_ICONERROR, '_IECreate', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(1,0,0)
    Endif
    Sleep(1000) <----------------------------------< THIS !

It is here because there is a redirection and without it, it doesn't work.

_IELoadWait dosen't work cause maybe of the redirection.

Share this post


Link to post
Share on other sites
On 11/15/2019 at 3:26 PM, Nine said:

You could loop on $hCtrl = ControlGetHandle($hIE,"","[Class:DirectUIHWND]") until $hCtrl is not 0 ?

Doesn't work, i tested and the redirection is very fast, but the page loading is slow and this is why i have to put a Sleep.

If i don't, my button clicks don't work just after that :

Local $oBouttonDL = _IEGetObjById($oIE, 'ext-gen76')
    If @error Then
        MsgBox($MB_ICONERROR, '_IEGetObjById1', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(2,0,0)
    Endif
    _IEAction($oBouttonDL, 'click')

    Local $oBouttonOK = _IEGetObjById($oIE, 'ext-gen174')
       If @error Then
        MsgBox($MB_ICONERROR, '_IEGetObjById2', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(2,0,0)
    Endif

There must be a way to detect if page is correctly loaded without using _IELoadWait.

Edit : The loop that works is :

Local $oBouttonDL = 0
    While $oBouttonDL = 0
        Sleep(50)
        $oBouttonDL = _IEGetObjById($oIE, 'ext-gen76')
    WEnd

I don't know if it's a good way but it works for me.

 

The problem now, is that i would like to detect when the download initiated is finished, in order to _IEQuit($oIE) without closing the Save As window or shutting down IE in the middle of download.

Maybe a COM usage ?

Here's the full code for lisibility :

Func _DL()
_IEErrorHandlerRegister(_User_ErrFunc)

    Local $urldl = $aCSV[GUICtrlRead($tab) * 4 + 3]
    Local $oIE = _IECreate($urldl);, 0, 0, 1, 0)
    If @error Then
        MsgBox($MB_ICONERROR, '_IECreate', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(1,0,0)
    Endif
    
    Local $oBouttonDL = 0
    While $oBouttonDL = 0
        Sleep(50)
        $oBouttonDL = _IEGetObjById($oIE, 'ext-gen76')
    WEnd
    _IEAction($oBouttonDL, 'click')

    Local $oBouttonOK = _IEGetObjById($oIE, 'ext-gen164')
       If @error Then
        MsgBox($MB_ICONERROR, '_IEGetObjById2', '@error = ' & @error & @CRLF & '@extended = ' & @extended)
        Return SetError(2,0,0)
    Endif
    _IEAction($oBouttonOK, 'click')
    Sleep(500)

Local $hIE = WinGetHandle("[Class:IEFrame]")
Local $hCtrl = ControlGetHandle($hIE,"","[Class:DirectUIHWND]")
Local $aPos = ControlGetPos($hIE,"",$hCtrl)
Local $x = $aPos[2]-160
Local $y = $aPos[3]-30

WinActivate($hIE) ; doesn't work in the background
ControlClick($hIE,"",$hCtrl,"primary",1,$x,$y) ; this only gives focus to the save button
ControlSend($hIE,"",$hCtrl,"{down}") ; this does work once the save button is focussed
ControlSend($hie, "", "[Class:DirectUIHWND]","s")

; save as - Dont need to change any of this except for filepath.
WinActivate("Enregistrer sous", "Enregistrer");
WinWaitActive("Enregistrer sous", "Enregistrer", 10);
ControlSetText("Enregistrer sous", "", "Edit1", @DesktopDir)
ControlClick("Enregistrer sous", "", "&Enregistrer", "left", 1, 5, 5)

; _IEQuit($oIE) <---------<------<----- Here
EndFunc   ;==>_DL

 

Edited by JoeBar

Share this post


Link to post
Share on other sites
4 minutes ago, Nine said:

Loop for FileGetSize (...) until it is no longer equals to 0. It is working perfect for small files, never tested on large files yet. 

So i must capture the Folder and the filename when the Save As window is active before that.

It's not a bad idea, i will test that when i have time. 😊

 

P.S : @Nine J'ai vu que t'étais Français, merci du coup de main ;)

Share this post


Link to post
Share on other sites

Can i get informations about IE pending download (or an event when DL is finished) with COM or other ?

It's for large files and i have no way to know the final file size so i cannot check when the file is fully written ...

Edited by JoeBar

Share this post


Link to post
Share on other sites

Can you use InetGet instead of manipulating IE to get your file? You might need to manipulate IE to get the full path to the file you're trying to get.

Alternately, can you map a network drive to the NAS? If you can do that, you can use FileCopy to get it instead, which will make your life waaay easier :)


All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Share this post


Link to post
Share on other sites

Yashied has written something like this awhile ago :

#Include <WinAPI.au3>

MsgBox ($MB_SYSTEMMODAL,"",IsFileInUse ("Temp.xls"))

Func IsFileInUse ($sFile)
    Local $hFile = _WinAPI_CreateFile($sFile, 2, 2, 0)
    If $hFile Then
        _WinAPI_CloseHandle($hFile)
        Return 0
    EndIf
    Local $Error = _WinAPI_GetLastError()
    Switch $Error
        Case 32 ; ERROR_SHARING_VIOLATION
            Return 1
        Case Else
            Return SetError($Error, 0, 0)
    EndSwitch
EndFunc   ;==>IsFileInUse

Check if it is working with your downloaded files...

Share this post


Link to post
Share on other sites
1 hour ago, seadoggie01 said:

Can you use InetGet instead of manipulating IE to get your file? You might need to manipulate IE to get the full path to the file you're trying to get.

Alternately, can you map a network drive to the NAS? If you can do that, you can use FileCopy to get it instead, which will make your life waaay easier :)

Hi, I've clearly written in the 1st post, i couldn't InetGet because the file is generated and only downloadable one time.

I'm trying download interception (with Events), but InetGet downloads a 38kB json file that says "Error" (Badboy message).

I think the server interprets InetGet as a new connection and discard it. The same if i copy/paste the good link in IE (says that i'm not authed)

One solution would be that InetGet acts as the IE connection (to not be detected) when i intercept the download, but in fact, it creates another connection and it's the same as below.

 

I found an API which easily makes all that i want (Synology), but i would want to manage to finish it as we are near the solution.

Edited by JoeBar

Share this post


Link to post
Share on other sites
44 minutes ago, Nine said:

Yashied has written something like this awhile ago :

#Include <WinAPI.au3>

MsgBox ($MB_SYSTEMMODAL,"",IsFileInUse ("Temp.xls"))

Func IsFileInUse ($sFile)
    Local $hFile = _WinAPI_CreateFile($sFile, 2, 2, 0)
    If $hFile Then
        _WinAPI_CloseHandle($hFile)
        Return 0
    EndIf
    Local $Error = _WinAPI_GetLastError()
    Switch $Error
        Case 32 ; ERROR_SHARING_VIOLATION
            Return 1
        Case Else
            Return SetError($Error, 0, 0)
    EndSwitch
EndFunc   ;==>IsFileInUse

Check if it is working with your downloaded files...

I'm on the way for another way to download, but if i fail to, i will give it a try ;)

Edited by JoeBar

Share this post


Link to post
Share on other sites
1 hour ago, JoeBar said:

Hi, I've clearly written in the 1st post, i couldn't InetGet because the file is generated and only downloadable one time.

Sorry, there's only so much I can read before I get distracted. Coffee + ADD does that to you :D

Related API that I found if anyone is interested: https://global.download.synology.com/download/Document/Software/DeveloperGuide/Package/FileStation/All/enu/Synology_File_Station_API_Guide.pdf I would switch to using the API if possible, it sounds like any solution beyond this point will be sketchy.

Would it work to try and copy the file to see if it's being used? You shouldn't be able to copy a file that's being downloaded, right?

If not, there is a Download Complete event in IE. Maybe someone knows how to listen for this in AutoIt. The event sounds like it also fires at the end of a page navigation however.


All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Share this post


Link to post
Share on other sites
41 minutes ago, seadoggie01 said:

Sorry, there's only so much I can read before I get distracted. Coffee + ADD does that to you :D

Related API that I found if anyone is interested: https://global.download.synology.com/download/Document/Software/DeveloperGuide/Package/FileStation/All/enu/Synology_File_Station_API_Guide.pdf I would switch to using the API if possible, it sounds like any solution beyond this point will be sketchy.

Would it work to try and copy the file to see if it's being used? You shouldn't be able to copy a file that's being downloaded, right?

If not, there is a Download Complete event in IE. Maybe someone knows how to listen for this in AutoIt. The event sounds like it also fires at the end of a page navigation however.

I've found the API documentation (see 3 messages above yours) but i wanted to succeed with our method.

For the event, yes, it triggers when a page is loaded and i "don't know/don't want to try" if it triggers to when a file has been downloaded.

Edited by JoeBar

Share this post


Link to post
Share on other sites

I was taking a look at my code and I just use FileExists checks before opening the download. I just tested it with a large zip file and it won't open until the file is downloaded completely


All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...