Compare commits

...

2 Commits
v1.03 ... v1.05

Author SHA1 Message Date
Pete Batard
6f8c9cb6ed Improve localization handling
* Fix XML conversion error when localized language data contains escaped characters
* Fix connection error when requested locale is not handled by Microsoft's servers
* Also simplify Arch detection and return codes
* Closes #2
* Closes #3
2019-03-13 00:40:47 +00:00
Pete Batard
4cebdef31a Use translated messages for the PS 3.0 prompt
* Also use "Close" instead of "Cancel" for the initial 'Back' button
2019-03-12 13:58:06 +00:00

View File

@@ -1,5 +1,5 @@
# #
# Fido v1.03 - Retail Windows ISO Downloader # Fido v1.05 - Retail Windows ISO Downloader
# Copyright © 2019 Pete Batard <pete@akeo.ie> # Copyright © 2019 Pete Batard <pete@akeo.ie>
# ConvertTo-ImageSource: Copyright © 2016 Chris Carter # ConvertTo-ImageSource: Copyright © 2016 Chris Carter
# #
@@ -85,13 +85,6 @@ Add-Type -AssemblyName PresentationFramework
[Gui.Utils]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0) | Out-Null [Gui.Utils]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0) | Out-Null
#endregion #endregion
# Make sure PowerShell 3.0 or later is used (for Invoke-WebRequest)
if ($PSVersionTable.PSVersion.Major -lt 3) {
Write-Host Error: PowerShell 3.0 or later is required to run this script.
[System.Windows.MessageBox]::Show("PowerShell 3.0 or later is required to run this script.`nYou can download it from: https://www.microsoft.com/en-us/download/details.aspx?id=34595", "Error", "OK", "Error") | Out-Null
exit -1
}
#region Data #region Data
$WindowsVersions = @( $WindowsVersions = @(
@( @(
@@ -428,11 +421,12 @@ function Get-RandomDate()
#endregion #endregion
#region Globals #region Globals
$ErrorActionPreference = "Stop"
$dh = 58; $dh = 58;
$Stage = 0 $Stage = 0
$MaxStage = 4 $MaxStage = 4
$SessionId = "" $SessionId = ""
$ExitCode = -1 $ExitCode = 100
$Locale = "en-US" $Locale = "en-US"
$DFRCKey = "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main\" $DFRCKey = "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main\"
$DFRCName = "DisableFirstRunCustomize" $DFRCName = "DisableFirstRunCustomize"
@@ -447,23 +441,43 @@ $UserAgent = "Mozilla/5.0 (X11; Linux i586; rv:$FirefoxVersion.0) Gecko/$Firefox
#endregion #endregion
# Localization # Localization
$EnglishMessages = "en-US|Version|Release|Edition|Language|Architecture|Download|Continue|Back|Close|Cancel|Error|Please wait...|Download using a browser|Temporarily banned by Microsoft for requesting too many downloads - Please try again later..." $EnglishMessages = "en-US|Version|Release|Edition|Language|Architecture|Download|Continue|Back|Close|Cancel|Error|Please wait...|" +
"Download using a browser|Temporarily banned by Microsoft for requesting too many downloads - Please try again later...|" +
"PowerShell 3.0 or later is required to run this script.|Do you want to go online and download it?"
[string[]]$English = $EnglishMessages.Split('|') [string[]]$English = $EnglishMessages.Split('|')
[string[]]$Localized = $null [string[]]$Localized = $null
if ($LocData -and (-not $LocData.StartsWith("en-US"))) { if ($LocData -and (-not $LocData.StartsWith("en-US"))) {
$Localized = $LocData.Split('|') $Localized = $LocData.Split('|')
if ($Localized.Length -ne $English.Length) { if ($Localized.Length -ne $English.Length) {
Write-Host "Error: Missing or extra translated messages provided ($($Localized.Length)/$($English.Length))" Write-Host "Error: Missing or extra translated messages provided ($($Localized.Length)/$($English.Length))"
exit 1 exit 101
} }
$Locale = $Localized[0] $Locale = $Localized[0]
} }
# Test if the Microsoft servers can handle our locale. If not, fall back to en-US.
$QueryLocale = $Locale
try {
$url = "https://www.microsoft.com/" + $QueryLocale + "/software-download/"
Invoke-WebRequest -UseBasicParsing -MaximumRedirection 0 -UserAgent $UserAgent $url | Out-Null
} catch {
$QueryLocale = "en-US"
}
# If asked, disable IE first run customize as it interferes with Invoke-WebRequest # Make sure PowerShell 3.0 or later is used (for Invoke-WebRequest)
if ($PSVersionTable.PSVersion.Major -lt 3) {
Write-Host Error: PowerShell 3.0 or later is required to run this script.
$Msg = "$(Get-Translation($English[15]))`n$(Get-Translation($English[16]))"
if ([System.Windows.MessageBox]::Show($Msg, $(Get-Translation("Error")), "YesNo", "Error") -eq "Yes") {
Start-Process -FilePath https://www.microsoft.com/download/details.aspx?id=34595
}
exit 102
}
# If asked, disable IE's first run customize prompt as it interferes with Invoke-WebRequest
if ($DisableFirstRunCustomize) { if ($DisableFirstRunCustomize) {
try { try {
# Only create the key if it doesn't already exist # Only create the key if it doesn't already exist
Get-ItemProperty -Path $DFRCKey -Name $DFRCName -ErrorActionPreference "Stop" Get-ItemProperty -Path $DFRCKey -Name $DFRCName
} catch { } catch {
if (-not (Test-Path $DFRCKey)) { if (-not (Test-Path $DFRCKey)) {
New-Item -Path $DFRCKey -Force | Out-Null New-Item -Path $DFRCKey -Force | Out-Null
@@ -487,7 +501,7 @@ if ($Locale.StartsWith("ar") -or $Locale.StartsWith("fa") -or $Locale.StartsWit
} }
$WindowsVersionTitle.Text = Get-Translation("Version") $WindowsVersionTitle.Text = Get-Translation("Version")
$Continue.Content = Get-Translation("Continue") $Continue.Content = Get-Translation("Continue")
$Back.Content = Get-Translation("Cancel") $Back.Content = Get-Translation("Close")
# Populate the Windows versions # Populate the Windows versions
$i = 0 $i = 0
@@ -518,7 +532,7 @@ $Continue.add_click({
$XMLForm.Title = Get-Translation($English[12]) $XMLForm.Title = Get-Translation($English[12])
Refresh-Control($XMLForm) Refresh-Control($XMLForm)
$url = "https://www.microsoft.com/" + $Locale + "/software-download/" $url = "https://www.microsoft.com/" + $QueryLocale + "/software-download/"
$url += $WindowsVersion.SelectedValue.PageType $url += $WindowsVersion.SelectedValue.PageType
Write-Host Querying $url Write-Host Querying $url
@@ -567,7 +581,7 @@ $Continue.add_click({
} }
3 { # Product Edition selection => Request and populate Languages 3 { # Product Edition selection => Request and populate Languages
$url = "https://www.microsoft.com/" + $Locale + "/api/controls/contentinclude/html" $url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
$url += "?pageId=" + $RequestData["GetLangs"][0] $url += "?pageId=" + $RequestData["GetLangs"][0]
$url += "&host=www.microsoft.com" $url += "&host=www.microsoft.com"
$url += "&segments=software-download," + $WindowsVersion.SelectedValue.PageType $url += "&segments=software-download," + $WindowsVersion.SelectedValue.PageType
@@ -587,7 +601,9 @@ $Continue.add_click({
throw "Unexpected server response" throw "Unexpected server response"
} }
$html = $($r.AllElements | ? {$_.id -eq "product-languages"}).InnerHTML $html = $($r.AllElements | ? {$_.id -eq "product-languages"}).InnerHTML
$html = "<options>" + $html.Replace("selected value", "value") + "</options>" $html = $html.Replace("selected value", "value")
$html = $html.Replace("&", "&amp;")
$html = "<options>" + $html + "</options>"
$xml = [xml]$html $xml = [xml]$html
foreach ($var in $xml.options.option) { foreach ($var in $xml.options.option) {
$json = $var.value | ConvertFrom-Json; $json = $var.value | ConvertFrom-Json;
@@ -615,7 +631,7 @@ $Continue.add_click({
} }
4 { # Language selection => Request and populate Arch download links 4 { # Language selection => Request and populate Arch download links
$url = "https://www.microsoft.com/" + $Locale + "/api/controls/contentinclude/html" $url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
$url += "?pageId=" + $RequestData["GetLinks"][0] $url += "?pageId=" + $RequestData["GetLinks"][0]
$url += "&host=www.microsoft.com" $url += "&host=www.microsoft.com"
$url += "&segments=software-download," + $WindowsVersion.SelectedValue.PageType $url += "&segments=software-download," + $WindowsVersion.SelectedValue.PageType
@@ -651,25 +667,14 @@ $Continue.add_click({
$json = $var.value | ConvertFrom-Json; $json = $var.value | ConvertFrom-Json;
if ($json) { if ($json) {
$Type = $json.DownloadType $Type = $json.DownloadType
# Maybe Microsoft will provide public ARM/ARM64 retail ISOs one day... if ($Type -eq "IsoX64") {
if ($Type -like "*arm64*") {
$Type = "Arm64"
if ($ENV:PROCESSOR_ARCHITECTURE -eq "ARM64") {
$SelectedIndex = $i
}
} elseif ($Type -like "*arm*") {
$Type = "Arm"
if ($ENV:PROCESSOR_ARCHITECTURE -eq "ARM") {
$SelectedIndex = $i
}
} elseif ($Type -like "*x64*") {
$Type = "x64" $Type = "x64"
if ($ENV:PROCESSOR_ARCHITECTURE -eq "AMD64") { if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") {
$SelectedIndex = $i $SelectedIndex = $i
} }
} elseif ($Type -like "*x86*") { } elseif ($Type -eq "IsoX86") {
$Type = "x86" $Type = "x86"
if ($ENV:PROCESSOR_ARCHITECTURE -eq "X86") { if ($env:PROCESSOR_ARCHITECTURE -eq "X86") {
$SelectedIndex = $i $SelectedIndex = $i
} }
} }
@@ -747,7 +752,7 @@ $Back.add_click({
$Back.Margin = $Margin $Back.Margin = $Margin
$script:Stage = $Stage - 1 $script:Stage = $Stage - 1
if ($Stage -eq 0) { if ($Stage -eq 0) {
$Back.Content = Get-Translation("Cancel") $Back.Content = Get-Translation("Close")
} elseif ($Stage -eq 3) { } elseif ($Stage -eq 3) {
$Continue.Content = Get-Translation("Continue") $Continue.Content = Get-Translation("Continue")
} }