Automate downloading files from Internet Explorer and saving them to a specified directory using AutoIT

I am facing a requirement to download a file from Internet Explorer 11 and save it to a specific location using Selenium and AutoIT. The path where the file should be saved is provided through the command line.

Below is the code I have implemented:

; Get the handle of the main window
Local $windHandle= WinGetHandle("[Class:IEFrame]", "")
Local $winTitle = "[HANDLE:" & $windHandle & "]"

; Select the "Save As" option
WinActivate ($winTitle, "")
Send("{F6}")
Sleep(500)
Send("{TAB}")
Sleep(500)
Send("{DOWN}")
Sleep(500)
Send("a")

; Save As dialog
; Wait for the "Save As" window
WinWait("Save As")
; Activate the "Save As" window
WinActivate("Save As")
ControlFocus("Save As","","Edit1")
ControlSetText("Save As","","Edit1",$CmdLine[1])
Sleep(2000)
ControlClick("Save As","","Button2")

===Execution of the code above through Selenium=====

Runtime.getRuntime().exec("D:\\AutoIT\\downloadFile.exe"+" "+"D:\\AutoIT\\abc.pdf");

The code works fine, but unfortunately, the file doesn't get saved in the specified location. It gets saved in the default location that the "Save As" window displays.

I would appreciate any help or insights on this matter.

Answer №1

Why do you insist on using the uncertain Send() command? AutoIt provides the INetGet() function for downloading files. I have created a simple download function with a small GUI that displays progress, speed, and remaining time. It may be beneficial for you:

#include <APIShellExConstants.au3>
#include <GuiStatusBar.au3>
#include <InetConstants.au3>
#include <ProgressConstants.au3>

; #FUNCTION# ====================================================================================================================
; Name ..........: _DownloadFile
; Description ...: Downloads a file from a specified URL, showing progress, speed, and remaining time.
; Syntax ........: _DownloadFile($_sUrl, $_sFile[, $_sTitle = 'Download'[, $_iWidth = -1[, $_iHeight = -1[, $_iX = -1[, $_iY = -1]]]]])
; Parameters ....: $_sUrl               - URL of the file to download.
; ...............: $_sFile              - Destination path for the downloaded file.
; ..[optional]...: $_sTitle             - Title of the download window. Default is '', = 'Download'.
; ..[optional]...: $_iWidth             - Width of the download window. Default is -1, = 250.
; ..[optional]...: $_iHeight            - Height of the download window. Default is -1, = 75.
; ..[optional]...: $_iX                 - X position of the download window. Default is -1, centered. Other negative value: X px from right, postive values: X px absolute.
; ..[optional]...: $_iY                 - Y position of the download window. Default is -1, centered. Other negative value: Y px from bottom, postive values: Y px absolute.
; Return values .: Success              None
; ...............: Failure              1 - Download failed or was interrupted.
; Author ........: BugFix
; ===============================================================================================================================
Func _DownloadFile($_sUrl, $_sFile, $_sTitle='', $_iWidth=-1, $_iHeight=-1, $_iX=-1, $_iY=-1) ; Pos: -1/-1 = center, -X/-Y = X px from right / Y px from bottom
    $_sTitle = $_sTitle = '' ? 'Download' : $_sTitle
    $_iWidth = $_iWidth = -1 ? 250 : $_iWidth
    $_iHeight = $_iHeight = -1 ? 75 : $_iHeight
    If FileExists($_sFile) Then FileMove($_sFile, $_sFile & '.bak', 1)

    ; Download in background, wait until DL complete - show it in GUI
    Local $iBytesSize, $hDL = GUICreate($_sTitle, $_iWidth, $_iHeight, -1, -1, BitOR(0x00C00000,0x00080000)) ; WS_CAPTION,WS_SYSMENU
    Local $idDL_sum = GUICtrlCreateLabel('0,000 KB', 5, 5, $_iWidth-10, 30, 0x01) ; SS_CENTER
    GUICtrlSetFont(-1, 14, Default, Default, 'Verdana')
    Local $aParts[3] = [75,$_iWidth-75,-1]
    Local $hStatus = _GUICtrlStatusBar_Create($hDL, $aParts)
    _GUICtrlStatusBar_SetMinHeight($hStatus, 25)
    Local $idProgress = GUICtrlCreateProgress(0, $_iHeight-20-26, $_iWidth, 20, $PBS_SMOOTH)
    Local $iTimer = TimerInit()
    ; get absolute window size, move window
    Local $aWin = WinGetPos($hDL)
    Select
        Case $_iX = -1
            $_iX = (@DesktopWidth - $aWin[2]) / 2
        Case $_iX < -1
            $_iX = @DesktopWidth - ($aWin[2] - $_iX)
    EndSelect
    Select
        Case $_iY = -1
            $_iY = (@DesktopHeight - $aWin[3]) / 2
        Case $_iY < -1
            $_iY = @DesktopHeight - ($aWin[3] - $_iY)
    EndSelect
    WinMove($hDL, '', $_iX, $_iY)
    GUISetState()

    Local $iSizeSource = InetGetSize($_sUrl)
    Local $hDownload = InetGet($_sUrl, $_sFile, $INET_FORCERELOAD, $INET_DOWNLOADBACKGROUND)
    _GUICtrlStatusBar_SetText($hStatus, @TAB & _FormatByte($iSizeSource, '', False, 0), 2)

    Local $fEsc = False, $iDL_old = 0, $iDL_diff, $iTimeNeed
    Do
        If TimerDiff($iTimer) >= 1000 Then
            $iBytesSize = InetGetInfo($hDownload, $INET_DOWNLOADREAD)
            GUICtrlSetData($idDL_sum, StringReplace(_FormatByte($iBytesSize), '.', ','))
            GUICtrlSetData($idProgress, Int(($iBytesSize/$iSizeSource)*100))
            $iDL_diff = $iBytesSize - $iDL_old
            $iDL_old = $iBytesSize
            _GUICtrlStatusBar_SetText($hStatus, @TAB & _FormatByte($iDL_diff, '', False, '0') & '/s', 0)
            $iTimeNeed = ($iSizeSource - $iBytesSize) / $iDL_diff
            _GUICtrlStatusBar_SetText($hStatus, @TAB & _FormatSeconds($iTimeNeed), 1)
            $iTimer = TimerInit()
        EndIf
        If GUIGetMsg() = -3 Then
            $fEsc = True
            ExitLoop
        EndIf
    Until InetGetInfo($hDownload, $INET_DOWNLOADCOMPLETE)
    _GUICtrlStatusBar_SetText($hStatus, '', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 1)

    ; Get information about the downloaded file
    Local $aData = InetGetInfo($hDownload)
    If @error Or $fEsc Then
        FileDelete($_sFile)
        Local $sTmp = $fEsc ? 'escaped' : 'failed'
        GUICtrlSetData($idDL_sum, 'Download ' & $sTmp & '!')
        Return SetError(1,0,MsgBox(262192, 'Error', 'The Download has ' & $sTmp & '.'))
    Else
        GUICtrlSetData($idDL_sum, StringReplace(_FormatByte($iBytesSize), '.', ','))
        GUICtrlSetData($idProgress, 100)
        Sleep(500)
        GUICtrlSetData($idDL_sum, 'Download finished.')
    EndIf
    InetClose($hDownload)
    GUIDelete($hDL)
EndFunc  ;==>_DownloadFile


; #FUNCTION# ====================================================================================================================
; Name ..........: _FormatSeconds
; Description ...: Formats a given number of seconds into readable time format
; Syntax ........: _FormatSeconds($_sec)
; Parameters ....: $_sec                - The number of seconds.
; Return values .: The formatted time string.
; Author ........: BugFix
; ===============================================================================================================================
Func _FormatSeconds($_sec)
    Return ( $_sec < 60 ? StringFormat('00:00:%02u', $_sec) : _
             $_sec < 60*60 ? StringFormat('00:%02u', Floor($_sec/60)) & ':' & _
                    StringFormat('%02u', Mod($_sec,60)) : _
             $_sec < 60*60*24 ? StringFormat('%02u', Floor($_sec/3600)) & ':' & _
                    StringFormat('%02u', Floor(Mod($_sec,3600)/60)) & ':' & _
                    StringFormat('%02u', Mod(Mod($_sec,3600),60)) : _
             ( $_sec = 86400 ? "24:00:00" : Floor($_sec/86400) & ' d / ' & _
                    StringFormat('%02u', Floor(Mod($_sec,86400)/3600)) & ':' & _
                    StringFormat('%02u', Floor(Mod(Mod($_sec,86400),3600)/60)) & ':' & _
                    StringFormat('%02u', Mod(Mod(Mod($_sec,86400),3600),60)) & ' h') )
EndFunc  ;==>_FormatSeconds

; #FUNCTION# ====================================================================================================================
; Name ..........: _FormatByte
; Description ...: Formats byte values into readable units like TB, GB, MB, KB, or Byte
; Parameters ....: $_iByte    - Number of bytes to format
; ...............: $_sUnit    - Optional unit for displaying desired unit (TB, GB, MB, KB, Byte)
; ...............: $_fStruct  - Returns a structure with .TB .GB .MB .KB .Byte
; ...............: $_sDigit   - Number of decimal digits
; Return values .: The formatted string or structure.
; Author ........: BugFix
; ===============================================================================================================================
Func _FormatByte($_iByte, $_sUnit='', $_fStruct=False, $_sDigit='3')
    Local Static $aByte[5][2] = [[0x10000000000],[0x40000000],[0x100000],[0x400],[0x1]]
    Local Static $tBytes = DllStructCreate('int TB;int GB;int MB;int KB;int Byte;')
    Local Static $aUnit[5] = ['TB','GB','MB','KB','Byte']
    Local $iModulo = $_iByte, $iHighest = 4
    For $i = 0 To 3
        $aByte[$i][1] = $iModulo >= $aByte[$i][0] ? Floor($iModulo/$aByte[$i][0]) : 0
        $iModulo = $aByte[$i][1] > 0 ? Mod($iModulo,$aByte[$i][0]) : $iModulo
        $iHighest = $aByte[$i][1] > 0 ? ($i < $iHighest ? $i : $iHighest) : $iHighest
    Next
    $aByte[4][1] = $iModulo
    If $_fStruct Then
        $tBytes.TB   = $aByte[0][1]
        $tBytes.GB   = $aByte[1][1]
        $tBytes.MB   = $aByte[2][1]
        $tBytes.KB   = $aByte[3][1]
        $tBytes.Byte = $aByte[4][1]
        Return $tBytes
    EndIf
    $_sUnit = StringInStr('TB GB MB KB Byte', $_sUnit) ? $_sUnit : ''
    $_sUnit = $_sUnit = '' ? $aUnit[$iHighest] : $_sUnit
    Local $iUserUnit = Floor(StringInStr('TB GB MB KB Byte', $_sUnit)/3)
    If Number($_sDigit) < 0 Then $_sDigit = '0'
    Local $sFormat = '%.' & $_sDigit & 'f %s'
    Return StringFormat($sFormat, $_iByte/$aByte[$iUserUnit][0], $aUnit[$iUserUnit])
EndFunc  ;==>_FormatByte

Answer №2

Functionality is achieved, however the data isn't stored in a specific file location but rather defaults to wherever the "Save As" window indicates.

After some time and effort, I was able to solve this issue for my own project. Hopefully, others can benefit from this as well. It seems that the Address Bar for the folder path consists of a combination of Toolbar buttons and an Edit box. While I do not have precise knowledge of their structures, my understanding is that the Edit box is nested within ToolbarWindow32. When you click on the address bar (ToolbarWindow32) to manually input your own path, the Edit box becomes activated. Think of ToolbarWindow32 as the parent and the Edit box as the child. If anyone has more insight into this, please share.

Below is a functional example demonstrating different methods to achieve the same goal.

    #include <GuiToolbar.au3>
    #Include <File.au3>


    TestChangeSaveAsAddress()

    Func TestChangeSaveAsAddress()

        Run('Notepad.exe')
        WinWaitActive('Untitled - Notepad')
        Send('new line.')
        Send('^s')


        Local $AddressPath = 'K:\_DOC\_TEXT'
        Local $aFileName = 'New File.txt'
        ClipPut($AddressPath)                    ;for  Option 1

        Local $SaveAsTitle = '[CLASS:#32770; TITLE:Save As]'


    # I.a

        ;get 'Save As' window handle
        Local $hWnd = WinWaitActive($SaveAsTitle, '&Save', 10)

    # I.b

        ;get Address Bar handle for $AddressPath
        Local $hTollbars = ControlGetHandle($hWnd, 'Address', '[CLASSNN:ToolbarWindow324]')


    # II - IMPORTANT: Address Bar must be infocus in order to activate Edit2 to set $AddressPath in step (IV)
           ;Option 2 or 3 is highly recommended


        # ;Option 1 - Select ToolbarWindow32 - Address Bar (work around -not recomended)
        #------------------------------------------------------------------------------
    ;~         ControlFocus($hTollbars, 'Address', '')
    ;~         ControlSend($hTollbars, 'Address', '','{SPACE}')
    ;~         Send('^v{ENTER}')

        # ;Option 2 - Select ToolbarWindow32 - Address Bar (same as Option 3)
        #-------------------------------------------------------------------
             ControlCommand($hTollbars, "Address", "", "SendCommandID", 1280)

        # ;Option 3 - Select ToolbarWindow32 - Address Bar (same as Option 2)
        #------------------------------------------------------------------------------------------
    ;~         ControlCommand($hWnd, "Address", "ToolbarWindow324", "SendCommandID", 1280)

        # ;Option 4 - Select ToolbarWindow32 - Address Bar (mouse pointer also relocated)
        #------------------------------------------------------------------------------------------
    ;~        _GUICtrlToolbar_ClickIndex($hTollbars, -1,'Left',True,1,0)

        # ;Option 5 - Select ToolbarWindow32 - Address Bar (this simulate as Run, NOT RunWait if your project required it - NOT Recommended)
        #------------------------------------------------------------------------------------------
    ;~      Run(@AutoItExe & ' /AutoIt3ExecuteLine "ControlCommand ( hwnd(' & $hWnd & '),'''', hwnd(' & $hTollbars & '), ''SendCommandID'', 1280 )"')


    # III
            ;check if path $AddressPath exists
            If Not FileExists($AddressPath) Then DirCreate($AddressPath)

    # IV
            ;set new path
            ControlSetText($hWnd, "Address", 'Edit2', $AddressPath)
    ;~         ControlFocus($hTollbars,'Address','')


    # V
            ;commit new Path
            ControlSend($hWnd, "Address", 'Edit2','{ENTER}')

    # VI
            ;set new file name
            ControlSetText($hWnd, "Namespace", "Edit1", $aFileName)
            ControlFocus($hWnd,'Namespace','Edit1')

    # VII
            ;allow manual keypress {SPACE} or {ENTER} to save/cancel
    ;~         ControlFocus($hWnd,'&Save','Button1')
    ;~         ControlFocus($hWnd,'Cancel','Button2')

    # VIII
            ;auto click save/cancel
    ;~         ControlClick($hWnd,"&Save", 'Button1','Left')
    ;~         ControlClick($hWnd,"Cancel", 'Button2','Left')


    # IX
        #--------------------------------------------------
        # ---OR--- skip all above steps and use this work around
        #--------------------------------------------------
    ;~     ControlSetText($hWnd, "Namespace", "Edit1", $AddressPath&'\'&$aFileName)

    EndFunc

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting Timeout Problems with Selebiun Crawler in C#

I am encountering an error while running the following code. public void GetCategoriesSelenium() { string javascript = System.IO.File.ReadAllText(@"GetCategory.js"); CrawlerWebSeleniumJS.ExecuteScript("var finished;"); ...

What is the best way to duplicate an entire webpage with all its content intact?

Is it possible to copy an entire page including images and CSS using Selenium? Traditional methods like ctrl + a or dragging the mouse over the page do not seem to work. How can this be achieved with Selenium without requiring an element to interact with? ...

Tips for waiting on image loading in canvas

My challenge involves interacting with the image loaded on a canvas. However, I am uncertain about how to handle waiting for the image to load before starting interactions with it in canvas tests. Using driver.sleep() is not a reliable solution. Here is ...

Can config values be dynamically set from an Excel file in Protractor?

I am currently working on parameterizing capabilities using an Excel sheet. For this task, I am utilizing the npm exceljs package for both reading and writing data. Below is a snippet of the code that demonstrates how I am trying to achieve this: //This f ...

I must interact with the video within the iframe by clicking on it

I am trying to interact with an iframe video on a webpage. Here is the code snippet for the video: <div class="videoWrapper" style="" xpath="1"> <iframe width="854" height="480" src="xxxxxxx" frameborder="0" allow="autoplay; encrypted-media" all ...

Can you tell me the distinction between using RemoteWebDriver's executeScript() and Selenium's getEval() for executing

Can you explain the distinction between these two pieces of code: RemoteWebDriver driver = new FirefoxDriver(); Object result = driver.executeScript("somefunction();"); and this: RemoteWebDriver driver = new FirefoxDriver(); Selenium seleniumDriver = ne ...

waiting for elements in Nightwatch.js using FluentWait

I am seeking assistance on implementing FluentWait using nightwatch.js. How can I achieve this? Within my project, I have a global.js file that includes: waitForConditionPollInterval : 300, waitForConditionTimeout : 5000, However, it seems like this ...

Is it possible to access a hidden JavaScript variable in Selenium?

Is there a way to extract the array "o" that contains data used for drawing a polygon? Simply using driver.execute("return o") or console.log doesn't seem to work. Any suggestions on how to achieve this? const zt = function(e, t, n, r) { c ...

Does AngularJS have a feature similar to jQuery.active?

As I utilize selenium to conduct tests on my application, I am encountering numerous ajax calls that utilize $resource or $http. It would be convenient if there was a method in angular to monitor active ajax requests so that selenium could wait until they ...

Having trouble with accessing an element that contains both onclick and text attributes in Selenium Webdriver?

The HTML code I'm dealing with includes this element: <a style="text-decoration:none; font-weight:normal;" href="javascript:void(0);" onclick="CreateNewServiceItemApproved();"> <img src="icons/ui/addnew.png"> <span style="color:# ...

Unable to transform data types

Currently, I am studying the JavaScript for automation session at WWDC. Here is an example taken from slide 99 that I am working on. On a fresh installation of Yosemite, I encountered an error on line 3. Safari = Application('Safari') doc = Safa ...

Steps for creating an HTML report using Intern JS

Our team relies on intern JS for automating functional tests, however we are facing difficulty in generating an html report. I attempted to use locvhtml as suggested by the Intern documentation (https://theintern.github.io/intern/#reporter-lcov), but unfo ...

Mastering Protractor's end-to-end control flow and managing time outs

When testing an angular app using protractor, I encountered a strange issue recently. Every now and then, or since a recent update, protractor seems to stall or slow down significantly. After investigating the problem, I discovered that a simple someEleme ...

Can you explain the meaning of arguments[0] and arguments[1] in relation to the executeScript method within the JavascriptExecutor interface in Selenium WebDriver?

When utilizing the executeScript() method from the JavascriptExecutor interface in Selenium WebDriver, what do arguments[0] and arguments[1] signify? Additionally, what is the function of arguments[0] in the following code snippet. javaScriptExecutor.ex ...

Selenium in C#: Timeout issue with SendKeys and Error thrown by JS Executor

Attempting to insert the large amount of data into the "Textarea1" control, I have tried two different methods. The first method successfully inserts the data but occasionally throws a timeout error, while the second method results in a JavaScript error. A ...

The Protractor Custom Locator is experiencing difficulty in finding the element

For our project, the automation team is incorporating a custom attribute called 'lid' to elements where unique identification is challenging. A new custom locator method has been developed to find elements using the 'lid' attribute: ...

Tips for effectively managing dynamic xpaths

When conducting a search operation, I am required to select the text that is returned as a result. Each search will produce different xpaths. Below are examples of various xpaths returned during a search: .//*[@id='messageBoxForm']/div/div[1]/di ...

Guide on setting an attribute value with JavaScriptExecutor in Selenium WebDriver

I am attempting to set an attribute value for all instances of the same type of <img> tag on My website, for example: <img src="images/temp/advertisement.png"> and I want to set style="display: none" so that I can hide them. I have tried the ...

Unable to retrieve the text enclosed between the:: before and after the:: marker

I attempted this using the XPATH finder in Chrome, and it highlighted the element. However, when running my Selenium script, I received the following error: Caused by: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: ...

Converting HTML Javascript to JAVA with the help of Selenium

Can someone help me extract the value of h1 as a string using selenium? Check out the HTML javascript snippet below- <script type="text/javascript"> $(window).load(function() { var $windowHeight = $(window).height() -12; $(" ...