Search code examples
windowspowershellboostwebrequest

How to download and run installer with PowerShell?


I am trying to download and execute an installer (of Boost 1.74) on Windows PowerShell for a CI system:

I am using Invoke-WebRequest and after that simply execute the program. However it tells me that file is corrupt. I tried several times and I don't think the file is corrupt but perhaps there is a problem with the permissions.

$ Invoke-WebRequest 'https://downloads.sourceforge.net/project/boost/boost-binaries/1.74.0/boost_1_74_0-msvc-14.2-64.exe' -OutFile 'boost_1_74_0-msvc-14.2-64.exe'
$ ./boost_1_74_0-msvc-14.2-64.exe
Program 'boost_1_74_0-msvc-14.2-64.exe' failed to run: The file or directory is corrupted and unreadableAt line:323 
char:1
+ ./boost_1_74_0-msvc-14.2-64.exe
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.
At line:323 char:1
+ ./boost_1_74_0-msvc-14.2-64.exe
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [], ApplicationFailedException
    + FullyQualifiedErrorId : NativeCommandFailed

How can I make sure the installer is executed here? What am I doing wrong?


NOTE: I am using this link (that according to the comments just points to a small text file with another web address) because it is the one used by Chocolatey installer.

# Install 64 bit binaries
Install-ChocolateyPackage `
    -packageName 'boost-msvc-14.2' `
    -installerType 'exe' `
    -silentArgs '/VERYSILENT' `
    -url64bit 'https://downloads.sourceforge.net/project/boost/boost-binaries/1.74.0/boost_1_74_0-msvc-14.2-64.exe' `
    -checksum64 74229a45b1e13f05c5bbdca7a268ac7723d97c33bec209e5f669b6cb3ffaeab6 `
    -checksumType64 sha256

Solution

  • To add to Someone's helpful answer:

    • Despite its appearance, URL https://downloads.sourceforge.net/project/boost/boost-binaries/1.74.0/boost_1_74_0-msvc-14.2-64.exe does not directly target a downloadable file.

    • When you open this URL interactively in a web browser:

      • An HTML page with embedded JavaScript code opens, and it is only on execution of the latter that a file download is initiated (by presenting a file-download (Save As) dialog) - a mechanism that is unrelated to HTTP redirects (302).
    • When you use curl to target the URL:

      • A 302 HTTP redirect occurs, and the true file-download URL is redirected to.

      • Therefore, an alternative solution is to use the following (on Unix-like platforms, use curl instead of curl.exe):

        curl.exe -L https://downloads.sourceforge.net/project/boost/boost-binaries/1.74.0/boost_1_74_0-msvc-14.2-64.exe -o boost_1_74_0-msvc-14.2-64.exe
        
    • The target web server decides which of the two behaviors to apply based on the user-agent string provided by the client.

      • The user-agent string provided by PowerShell's web cmdlets, Invoke-WebRequest and Invoke-RestMethod by default - unfortunately - triggers the browser behavior. That user-agent string looks something like this:

        • In Windows PowerShell:

          Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.22621.3672
          
        • In PowerShell (Core) 7 on Windows:

          Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.22621; en-US) PowerShell/7.4.2
          
      • The browser-like behavior is problematic, because PowerShell's web cmdlets by design support downloading static content only, which means that targeting said URL results in downloading the raw HTML source code, with no execution of embedded JavaScript.

        • Potentially changing this problematic default user-agent string is the subject of GitHub issue #24425.
      • It is therefore the raw HTML that is saved to the specified -OutFile, which is obviously not a proper .exe file and on invocation causes the error you saw.

    • It follows from the above that you can make PowerShell's web cmdlets work as expected by using the -UserAgent parameter to specify a curl-like user-agent string that triggers the HTTP-redirect behavior:

      Invoke-WebRequest -UserAgent curl https://downloads.sourceforge.net/project/boost/boost-binaries/1.74.0/boost_1_74_0-msvc-14.2-64.exe -OutFile boost_1_74_0-msvc-14.2-64.exe
      
      • Note that PowerShell's web cmdlets - unlike curl, which requires -L - follow HTTP redirects by default, up to 5 times. To modify this number, use the -MaximumRedirection parameter.