Powershell download file from redirecting url - TeamViewer & Intune - powershell

Thank you in advance for anyone taking a look into this.
I'm currently trying to deploy TeamViewer via Intune that only support MSI files for deployment. However, TeamViewer has a feature called account assignment which it comes in form of an executable. Since Intune doesn't allow you deploy exe files, please correct me if I'm wrong. I have resulted in using a PowerShell script that will download the necessary files and then install.
My goal is to have the files stored in the cloud like onedrive or Dropbox. The problem there is the public link doesn't point to the file directly as its a redirect.
For example https://www.dropbox.com/x/xyzd/TeamViewer_Assignment.exe?dl=0 --> https://www.dropbox.com/x/xyzd/TeamViewer_Assignment.exe
or
https://1drv.ms/u/s!Avjfi0upMYg9haNVTMpdoPGdstex --> https://1drv.ms/u/s/teamviewer.exe
if both links were to end with the file extension (.exe), then it would be no problem. But I would like to use Teamviewer links (get.teamviewer.com/myhost redirects https://download.teamviewer.com/u/id12345/TeamViewer.exe hoping this will help a lot more people. As opposed to having a cloud storage account.
https://download.teamviewer.com/u/id12345/TeamViewer.exe is not a permanent link either, and it has an expiration time.
Things I've tried:
$url = "https://get.teamviewer.com/mycustomhost"
$output = "$PSScriptRoot\myhost.exe"
$start_time = Get-Date
Invoke-WebRequest -Uri $url -OutFile $output
Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds)
second(s)"
$url = "http://get.teamviewer.com/myhost"
$output = "$PSScriptRoot\myhost.exe"
$start_time = Get-Date
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($url, $output)
#OR
(New-Object System.Net.WebClient).DownloadFile($url, $output)
Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds)
second(s)"
$rep=Invoke-WebRequest
http://www.get.teamviewer.com/myhost -MaximumRedirection
0
$rep.Links | where {$_.innerText -eq "click here"} |select -expand href
None of those examples worked I tried other combination from bits and pieces over the net but no go.

You can use the following URI for all of your examples:
https://customdesign.teamviewer.com/download/version_12x/myhost/TeamViewerQS.exe
You can get this URI for your download in Chrome in the following way:
Download TeamViewer
Open the Download History
Right click the entry for the TeamViewer download and copy the download URI.
Edit:
You can parse the download site for the real link with the following command:
$downloadPage = Invoke-WebRequest -Uri https://get.teamviewer.com/myhost
$downloadLink = $request.ParsedHtml.getElementById('MasterBodyContent_btnRetry').href
Now you can use the '$downloadLink' variable to download the executable with any of your scripts. You may have to change this if the download page for TeamViewer changes.
Just search for the id of the 'Try again' button on the download page. Then you can edit my code to get the appropriate element and attribute.

Related

Download file from website using SendKeys in Powershell

I'm trying to download an file from a particular website by clicking on the file icon. Website login works but i'm hoping to use keystroke "TAB" to navigate to the excel file and finally key "Enter" to download. Ran the code but resulted in the Powershell text of "FALSE". Any advice is appreciated! Thanks.
Reference: Table screenshot
$url = "https://abcdefg.com"
$username="test#gmail.com"
$password="TestPW"
$ie = New-Object -com internetexplorer.application;
$ie.visible = $true;
$ie.navigate($url);
while ($ie.Busy -eq $true)
{
Start-Sleep -Milliseconds 1000;
}
$ie.Document.getElementById("txtEmail").value = $username
$ie.Document.getElementByID("txtPassword").value=$password
$ie.Document.getElementById("Login").Click();
Start-Sleep -Milliseconds 10000
$obj = new-object -com WScript.Shell
$obj.AppActivate('Internet Explorer')
$obj.SendKeys('{TAB}')
$obj.SendKeys('{TAB}')
$obj.SendKeys('{TAB}')
$obj.SendKeys('{TAB}')
$obj.SendKeys('{Enter}')
Why are you doing that vs using web scraping to find the link you are trying to hit, and use the link URL directly?
Your post is really a duplicate of this Q&A.
Use PowerShell to automate website login and file download
SendKeys could work, but they are very hinky and on different systems may not function as you'd expect. There are better tools dedicated to do this, AutoIT, Selenium, WASP
--- That WASP tool still works, but has not been updated in a long while.
Using PowerShell 2.0 With Selenium to Automate Internet Explorer, Firefox, and Chrome
Internet Explorer
Next you want to obtain the Internet Explorer driver from this site. I
recommend version 2.41 because “as of 15 April 2014, IE 6 is no longer
supported”. This must reside in your current PATH so in your script
you may want to modify your PATH to ensure the executable
(IEDriverServer.exe) can be found there. If you’re wondering whether
to get the 32-bit or the 64-bit version, start with the 32-bit even if
you’ve got a 64-bit Windows.
At this point you’ll want to quickly instantiate Internet Explorer and
navigate somewhere. Great. Let’s do it.
# Load the Selenium .Net library
Add-Type -Path "C:\selenium\WebDriver.dll" # put your DLL on a local hard drive!
# Set the PATH to ensure IEDriverServer.exe can found
$env:PATH += ";N:\selenium"
# Instantiate Internet Explorer
$ie_object = New-Object "OpenQA.Selenium.IE.InternetExplorerDriver"
# Great! Now we have an Internet Explorer window appear. We can navigate to a new URL:
$ie_object.Navigate().GoToURL( "http://www.bbc.co.uk/languages" )
# This worked! The call won’t return until the page download is complete.
# Next let’s click on a link from the link text:
$link = $ie_object.FindElementByLinkText( "Spanish" )
$link.Click()
# display current URL
$ie_object.Url
Selenium Tutorial: All You Need To Know About Selenium WebDriver
Update for the OP
As for...
However the file does not have a redirected URL
Then you need to look deeper at the site, to find the anchor to the file that you can force click on.
Example:
# Scrape a web page with PowerShell
$w = Invoke-WebRequest -Uri 'https://www.reddit.com/r/PowerShell'
$w | Get-Member
$w.AllElements
$w.AllElements.Count
$w.Links.Count
$w.Links
$w.Forms
$w.Forms.Fields
$w.Forms[0]
$w.Forms[0].Fields
$w.RawContent
$w.ParsedHtml
once you find tag names, or the like, you need to parse that to get stuff out of it.
$w.AllElements | Where-Object -Property 'TagName' -EQ 'P' | Select-Object -Property 'InnerText'
For tables you have to dig more.
Extracting Tables from PowerShell’s Invoke-WebRequest

Downloading a file with PowerShell

I have a URL to a CSV file which, in a browser, I can download and open without issue.
I'm trying to download this file using PowerShell without success. I tried using Invoke-WebRequest, Start-BitsTransfer and using a webrequest object but no luck there.
Invoke-WebRequest comes with a parameter to store its result in a file: -OutFile
Invoke-WebRequest $myDownloadUrl -OutFile c:\file.ext
If you need authorization before you can send a request like this:
Invoke-WebRequest $myAuthUrl /* whatever is neccesary to login */ -SessionVariable MySession
Invoke-WebRequest $myDownloadUrl -WebSession $MySession
To determine the layout of the form where the login happens, you can use Invoke-WebRequests return object. It'll collect information about forms and fields on the HTML (might be Windows only). Mileage of logging in may vary with things like Two-Factor-Auth active or not. Probably you can create some secret link to your file which does not need Auth or possibly google allows you to create a private access token of some sort, which can be send aus Authorization-Header alongside your request.
TLDR answers*:
Method 1, by default synchronous**
Invoke-WebRequest $url -OutFile $path_to_file
(if you get error "...Could not create SSL/TLS secure channel." see Powershell Invoke-WebRequest Fails with SSL/TLS Secure Channel)
Method 2, by default synchronous**
(New-Object System.Net.WebClient).DownloadFile($url, $path_to_file)
Method 3, asynchronous and may be much slower than the other two but is very gentle on bandwidth usage (it uses the BITS service).
Import-Module BitsTransfer
Start-BitsTransfer -Source $url -Destination $path_to_file
Notes:
*: This answer is for those that google for "how to download a file with PowerShell".
**: Read the help pages if you want asynchronous downloading
For a while now I've been using a PS script to download PowerBI bi-monthly and using the BITS, it's been pretty solid and now so much stronger now since I removed the -Asynchronous at the end of the Start-BitsTransfer
$url = "https://download.microsoft.com/download/8/8/0/880BCA75-79DD-466A-927D-1ABF1F5454B0/PBIDesktopSetup.exe"
$output = "%RandomPath%\PowerBI Pro\PBIDesktopSetup.exe"
$start_time = Get-Date
Import-Module BitsTransfer
Start-BitsTransfer -Source $url -Destination $output
#Commented out below because it kept creating "Tmp files"
#Start-BitsTransfer -Source $url -Destination $output -Asynchronous

Download secure file with PowerShell

I'm trying to create a new release task for VSTS which needs to download a secure file from the library. However, when I run the following PowerShell script no secure files are displayed but there are two in there. Could this be not having enough rights? What should be changed.
Another question: when I'm able to list the secure files I want to download a specific one. I haven't found any examples on how to do that. Does anyone know of an example?
$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/distributedtask/securefiles"
Write-Host "URL: $url"
$secureFiles = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "SecureFiles: $secureFiles"
I was able to download Secure Files using a REST API, the task's Access Token, and an Accept header for application/octet-stream. I enabled "Allow scripts to access the OAuth token". Here my task.json is using a secureFile named "SecureFile."
$secFileId = Get-VstsInput -Name SecureFile -Require
$secTicket = Get-VstsSecureFileTicket -Id $secFileId
$secName = Get-VstsSecureFileName -Id $secFileId
$tempDirectory = Get-VstsTaskVariable -Name "Agent.TempDirectory" -Require
$collectionUrl = Get-VstsTaskVariable -Name "System.TeamFoundationCollectionUri" -Require
$project = Get-VstsTaskVariable -Name "System.TeamProject" -Require
$filePath = Join-Path $tempDirectory $secName
$token= Get-VstsTaskVariable -Name "System.AccessToken" -Require
$user = Get-VstsTaskVariable -Name "Release.RequestedForId" -Require
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User, $token)))
$headers = #{
Authorization=("Basic {0}" -f $base64AuthInfo)
Accept="application/octet-stream"
}
Invoke-RestMethod -Uri "$($collectionUrl)$project/_apis/distributedtask/securefiles/$($secFileId)?ticket=$($secTicket)&download=true&api-version=5.0-preview.1" -Headers $headers -OutFile $filePath
I am using "$(Build.QueuedById)" to get the user id in build tasks, but honestly I don't think it matters what string you use there.
If you don't have the Accept header, you'll get JSON metadata back for the file you're attempting to download.
Unfortunately I cobbled this together from other SO posts and the github issues pages; I can't find anywhere official that documents the URL I'm using there.
There has no such REST API to download secure file, but you can use Download secure file task for assistants.
And since the secure file only exist in temporary location during build, you should download the secure file by Download secure file task firstly, and copy the secure file to another directory secondly:
1. Download secure file
You can add a Download secure file task (for VSTS) and specify the filename to download.
Note: since the task is not available for TFS, you can install the similar task like Download Secure File extension for your TFS account.
2. Copy secure file to another directory
Such as copy the secure file to $(Build.ArtifactStagingDirectory), you can use PowerShell script:
Copy-Item -Path $(Agent.WorkFolder)\_temp\filename -Destination $(Build.ArtifactStagingDirectory)
Or use Copy Files task to copy the secure file to $(Build.ArtifactStagingDirectory).
BTW:
Since you are using Download Secure File task (developed by Matt Labrum) which can only select secure file from DropDownList (variables can not be used). But there has an issue Enable to use a variable to specify the secure file to download which suggests this feature, you can follow up.
And for the REST API to download secure file, it's not available for now. But there has an user voice Access "Secure files" from .NET client library, and you can vote and follow up.

Powershell invoke-webrequest downloading HTML not actual file

I am trying to download a google spreadsheet via an invoke-webrequestin powershell.
My link looks something like this and I can confirm that if I go to the link it prompts me to download the file I want...
$url = https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXXXXX/export?format=csv
I have tried downloading the file via 2 ways:
Invoke-WebRequest $url -OutFile $saveLocation
(New-Object System.Net.WebClient).DownloadFile($url, $saveLocation)
Both of these just download the HTML for the page, and not the actual file.
The spreadsheet I am downloading is 100% public so it is not like I need to be logged into a google account to view it.
I made the test and I can quite safely say that your file is not public.
I have reproduced your issue before making my test sheet public, and I could not afterwards.
Tested with this :
$url = "https://docs.google.com/spreadsheets/d/1OOc5aiG3hh8mrGF4p7NJXKI8KqBSkS2ZjsBXtb4qpz8/export?format=csv"
Invoke-WebRequest $url -OutFile "C:\test.csv"

Trying to download a zip file from a weblink with powershell

Ok, I am trying to download a file off of a web link that we use with powershell. I am downloading a zip file where the begining of the name is always the same, but the the middle part will change based off of the version number of the zip. I have been able to get the file to download when I use the fully qualified web address and have the file name hard coded into the script. I have tried every version of using the wild cards to get all the most common version of the zip, but it errors out saying that it can't find the file on there server. This is the code that I have already, and any help would be greatly appreciated since I feel like I am at a wall with it.
$url = 'http://blah/blah/blah/My File Name 11.1111.11.zip'
$localFileName = 'C:\temp\MYzip.zip'
Invoke-WebRequest $url -UseDefaultCredentials -OutFile $localFileName
If the site has directory browsing enabled (unlikely unless you have control of the site and can turn it on), you can do this:
$url = 'http://blah/blah/blah/'
$wr = iwr $url
$filename = $wr.Links.href | Where {$_ -match 'My File Name.*?\.zip'}
$wr = iwr "$url/$filename"
If the site doesn't have directory browsing enabled then surely it has a page with a link to the ZIP file on it. Download that page and use the same $wr.Links.href trick to get all the links and look for the one that matches "My File Name.*?.zip".