Powershell/Applications/Edge/Force-Update.ps1
2023-07-04 12:59:44 +02:00

236 lines
9.1 KiB
PowerShell

<#
.SYNOPSIS
Get-EdgeEnterpriseMSI
.DESCRIPTION
Imports all device configurations in a folder to a specified tenant
.PARAMETER Channel
Channel to download, Valid Options are: Dev, Beta, Stable, EdgeUpdate, Policy.
.PARAMETER Platform
Platform to download, Valid Options are: Windows or MacOS, if using channel "Policy" this should be set to "any"
Defaults to Windows if not set.
.PARAMETER Architecture
Architecture to download, Valid Options are: x86, x64, arm64, if using channel "Policy" this should be set to "any"
Defaults to x64 if not set.
.PARAMETER Version
If set the script will try and download a specific version. If not set it will download the latest.
.PARAMETER Folder
Specifies the Download folder
.PARAMETER Force
Overwrites the file without asking.
.NOTES
Version: 1.2
Author: Mattias Benninge
Creation Date: 2020-07-01
Version history:
1.0 - Initial script development
1.1 - Fixes and improvements by @KarlGrindon
- Script now handles multiple files for e.g. MacOS Edge files
- Better error handling and formating
- URI Validation
1.2 - Better compability on servers (force TLS and remove dependency to IE)
https://docs.microsoft.com/en-us/mem/configmgr/apps/deploy-use/deploy-edge
.EXAMPLE
Download the latest version for the Beta channel and overwrite any existing file
.\Get-EdgeEnterpriseMSI.ps1 -Channel Beta -Folder D:\SourceCode\PowerShell\Div -Force
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $True, HelpMessage = 'Channel to download, Valid Options are: Dev, Beta, Stable, EdgeUpdate, Policy')]
[ValidateSet('Dev', 'Beta', 'Stable', 'EdgeUpdate', 'Policy')]
[string]$Channel = "Stable",
[Parameter(Mandatory = $True, HelpMessage = 'Folder where the file will be downloaded')]
[ValidateNotNullOrEmpty()]
[string]$Folder = "C:\temp",
[Parameter(Mandatory = $false, HelpMessage = 'Platform to download, Valid Options are: Windows or MacOS')]
[ValidateSet('Windows', 'MacOS', 'any')]
[string]$Platform = "Windows",
[Parameter(Mandatory = $false, HelpMessage = "Architecture to download, Valid Options are: x86, x64, arm64, any")]
[ValidateSet('x86', 'x64', 'arm64', 'any')]
[string]$Architecture = "x64",
[parameter(Mandatory = $false, HelpMessage = "Specifies which version to download")]
[ValidateNotNullOrEmpty()]
[string]$ProductVersion,
[parameter(Mandatory = $false, HelpMessage = "Overwrites the file without asking")]
[Switch]$Force
)
$ErrorActionPreference = "Stop"
$edgeEnterpriseMSIUri = 'https://edgeupdates.microsoft.com/api/products?view=enterprise'
# Validating parameters to reduce user errors
if ($Channel -eq "Policy" -and ($Architecture -ne "Any" -or $Platform -ne "Any")) {
Write-Warning ("Channel 'Policy' requested, but either 'Architecture' and/or 'Platform' is not set to 'Any'.
Setting Architecture and Platform to 'Any'")
$Architecture = "Any"
$Platform = "Any"
}
elseif ($Channel -ne "Policy" -and ($Architecture -eq "Any" -or $Platform -eq "Any")) {
throw "If Channel isn't set to policy, architecture and/or platform can't be set to 'Any'"
}
elseif ($Channel -eq "EdgeUpdate" -and ($Architecture -ne "x86" -or $Platform -eq "Windows")) {
Write-Warning ("Channel 'EdgeUpdate' requested, but either 'Architecture' is not set to x86 and/or 'Platform'
is not set to 'Windows'. Setting Architecture to 'x86' and Platform to 'Windows'")
$Architecture = "x86"
$Platform = "Windows"
}
Write-Host "Enabling connection over TLS for better compability on servers" -ForegroundColor Green
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
# Test if HTTP status code 200 is returned from URI
try {
Invoke-WebRequest $edgeEnterpriseMSIUri -UseBasicParsing | Where-Object StatusCode -match 200 | Out-Null
}
catch {
throw "Unable to get HTTP status code 200 from $edgeEnterpriseMSIUri. Does the URL still exist?"
}
Write-Host "Getting available files from $edgeEnterpriseMSIUri" -ForegroundColor Green
# Try to get JSON data from Microsoft
try {
$response = Invoke-WebRequest -Uri $edgeEnterpriseMSIUri -Method Get -ContentType "application/json" -UseBasicParsing -ErrorVariable InvokeWebRequestError
$jsonObj = ConvertFrom-Json $([String]::new($response.Content))
Write-Host "Succefully retrived data" -ForegroundColor Green
}
catch {
throw "Could not get MSI data: $InvokeWebRequestError"
}
# Alternative is to use Invoke-RestMethod to get a Json object directly
# $jsonObj = Invoke-RestMethod -Uri "https://edgeupdates.microsoft.com/api/products?view=enterprise" -UseBasicParsing
$selectedIndex = [array]::indexof($jsonObj.Product, "$Channel")
if (-not $ProductVersion) {
try {
Write-host "No version specified, getting the latest for $Channel" -ForegroundColor Green
$selectedVersion = (([Version[]](($jsonObj[$selectedIndex].Releases |
Where-Object { $_.Architecture -eq $Architecture -and $_.Platform -eq $Platform }).ProductVersion) |
Sort-Object -Descending)[0]).ToString(4)
Write-Host "Latest Version for channel $Channel is $selectedVersion`n" -ForegroundColor Green
$selectedObject = $jsonObj[$selectedIndex].Releases |
Where-Object { $_.Architecture -eq $Architecture -and $_.Platform -eq $Platform -and $_.ProductVersion -eq $selectedVersion }
}
catch {
throw "Unable to get object from Microsoft. Check your parameters and refer to script help."
}
}
else {
Write-Host "Matching $ProductVersion on channel $Channel" -ForegroundColor Green
$selectedObject = ($jsonObj[$selectedIndex].Releases |
Where-Object { $_.Architecture -eq $Architecture -and $_.Platform -eq $Platform -and $_.ProductVersion -eq $ProductVersion })
if (-not $selectedObject) {
throw "No version matching $ProductVersion found in $channel channel for $Architecture architecture."
}
else {
Write-Host "Found matching version`n" -ForegroundColor Green
}
}
if (Test-Path $Folder) {
foreach ($artifacts in $selectedObject.Artifacts) {
# Not showing the progress bar in Invoke-WebRequest is quite a bit faster than default
$ProgressPreference = 'SilentlyContinue'
Write-host "Starting download of: $($artifacts.Location)" -ForegroundColor Green
# Work out file name
$fileName = Split-Path $artifacts.Location -Leaf
if (Test-Path "$Folder\$fileName" -ErrorAction SilentlyContinue) {
if ($Force) {
Write-Host "Force specified. Will attempt to download and overwrite existing file." -ForegroundColor Green
try {
Invoke-WebRequest -Uri $artifacts.Location -OutFile "$Folder\$fileName" -UseBasicParsing
}
catch {
throw "Attempted to download file, but failed: $error[0]"
}
}
else {
# CR-someday: There should be an evaluation of the file version, if possible. Currently the function only
# checks if a file of the same name exists, not if the versions differ
Write-Host "$Folder\$fileName already exists!" -ForegroundColor Yellow
do {
$overWrite = Read-Host -Prompt "Press Y to overwrite or N to quit."
}
# -notmatch is case insensitive
while ($overWrite -notmatch '^y$|^n$')
if ($overWrite -match '^y$') {
Write-Host "Starting Download" -ForegroundColor Green
try {
Invoke-WebRequest -Uri $artifacts.Location -OutFile "$Folder\$fileName" -UseBasicParsing
}
catch {
throw "Attempted to download file, but failed: $error[0]"
}
}
else {
Write-Host "File already exists and user chose not to overwrite, exiting script." -ForegroundColor Red
exit
}
}
}
else {
Write-Host "Starting Download" -ForegroundColor Green
try {
Invoke-WebRequest -Uri $artifacts.Location -OutFile "$Folder\$fileName" -UseBasicParsing
}
catch {
throw "Attempted to download file, but failed: $error[0]"
}
}
if (((Get-FileHash -Algorithm $artifacts.HashAlgorithm -Path "$Folder\$fileName").Hash) -eq $artifacts.Hash) {
Write-Host "Calculated checksum matches known checksum`n" -ForegroundColor Green
}
else {
Write-Warning "Checksum mismatch!"
Write-Warning "Expected Hash: $($artifacts.Hash)"
Write-Warning "Downloaded file Hash: $((Get-FileHash -Algorithm $($artifacts.HashAlgorithm) -Path "$Folder\$fileName").Hash)`n"
}
}
}
Else {
throw "Folder $Folder does not exist"
}
Write-Host "-- Script Completed: File Downloaded -- " -ForegroundColor Green
Write-Host "Installing..." -ForegroundColor Green
cmd /c start /wait msiexec /i "$Folder\$fileName" /qn /norestart
Set-Service edgeupdate -StartupType Manual -ErrorAction SilentlyContinue
Set-Service edgeupdatem -StartupType Manual -ErrorAction SilentlyContinue
Unregister-ScheduledTask -TaskName MicrosoftEdgeUpdateTaskMachineCore -Confirm:$false -ErrorAction SilentlyContinue
Unregister-ScheduledTask -TaskName MicrosoftEdgeUpdateTaskMachineUA -Confirm:$false -ErrorAction SilentlyContinue
Write-Host "Installed Microsoft Edge" -ForegroundColor Green