mirror of
https://github.com/pbatard/Fido.git
synced 2025-09-16 14:18:02 +02:00
Hook up with Microsoft's web services
This commit is contained in:
273
DealBreaker.ps1
273
DealBreaker.ps1
@@ -77,7 +77,7 @@ function Add-Title([string]$Name)
|
||||
$Title.HorizontalAlignment = "Left"
|
||||
$Title.VerticalAlignment = "Top"
|
||||
$Margin = $WindowsVersionTitle.Margin
|
||||
$Margin.Top += $global:stage * $dh
|
||||
$Margin.Top += $script:stage * $script:dh
|
||||
$Title.Margin = $Margin
|
||||
$Title.Text = $Name
|
||||
return $Title
|
||||
@@ -92,16 +92,16 @@ function Add-Combo
|
||||
$Combo.HorizontalAlignment = "Left"
|
||||
$Combo.VerticalAlignment = "Top"
|
||||
$Margin = $WindowsVersion.Margin
|
||||
$Margin.Top += $global:stage * $dh
|
||||
$Margin.Top += $script:stage * $script:dh
|
||||
$Combo.Margin = $Margin
|
||||
$Combo.SelectedIndex = 0
|
||||
return $Combo
|
||||
}
|
||||
|
||||
# Form
|
||||
# XAML Form
|
||||
# TODO: Use relative extracted icon
|
||||
# TODO: Add FlowDirection = "RightToLeft" to <Window> for RTL mode
|
||||
[xml]$Form = @"
|
||||
<!-- TODO: use relative extracted icon -->
|
||||
<!-- TODO: Add FlowDirection = "RightToLeft" tp <Window> for RTL mode -->
|
||||
<Window xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" Title = "Windows ISO Download" Height = "162" Width = "380" ResizeMode = "NoResize" Icon="C:/rufus/res/icons/rufus.ico">
|
||||
<Grid Name = "Grid">
|
||||
<TextBlock Name = "WindowsVersionTitle" FontSize = "16" Width="340" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="16,8,0,0" Text="Windows Version"/>
|
||||
@@ -111,22 +111,27 @@ function Add-Combo
|
||||
</Window>
|
||||
"@
|
||||
|
||||
$XMLReader = (New-Object System.Xml.XmlNodeReader $Form)
|
||||
# Globals
|
||||
$dh = 58;
|
||||
$Stage = 0
|
||||
$SessionId = ""
|
||||
|
||||
$XMLReader = New-Object System.Xml.XmlNodeReader $Form
|
||||
$XMLForm = [Windows.Markup.XamlReader]::Load($XMLReader)
|
||||
$XMLGrid = $XMLForm.FindName("Grid")
|
||||
$Confirm = $XMLForm.FindName('Confirm')
|
||||
|
||||
# Fill in the first dropdown
|
||||
# Populate in the Windows Version dropdown
|
||||
$WindowsVersionTitle = $XMLForm.FindName('WindowsVersionTitle')
|
||||
$WindowsVersion = $XMLForm.FindName('WindowsVersion')
|
||||
$array = @()
|
||||
$i = 0
|
||||
foreach($Version in $WindowsVersions) {
|
||||
$null = $WindowsVersion.Items.Add($Version[0])
|
||||
$array += @(New-Object PsObject -Property @{ Version = $Version[0]; Index = $i })
|
||||
$i++
|
||||
}
|
||||
$VersionIndex = 0
|
||||
$ReleaseIndex = 0
|
||||
$Sku = 0
|
||||
$Stage = 0
|
||||
$dh = 58;
|
||||
$WindowsVersion.ItemsSource = $array
|
||||
$WindowsVersion.DisplayMemberPath = 'Version'
|
||||
|
||||
# Button Action
|
||||
$Confirm.add_click({
|
||||
@@ -135,6 +140,170 @@ $Confirm.add_click({
|
||||
}
|
||||
$script:Stage++
|
||||
|
||||
switch ($Stage) {
|
||||
|
||||
1 { # Windows Version selection => Check server connection and populate Windows Release
|
||||
$WindowsVersion.IsEnabled = $False;
|
||||
$Confirm.IsEnabled = $False
|
||||
# Force a refresh of the Confirm button so it is actually disabled
|
||||
$Confirm.Dispatcher.Invoke("Render", [Windows.Input.InputEventHandler] { $Confirm.UpdateLayout() }, $null, $null)
|
||||
|
||||
try {
|
||||
$r = Invoke-WebRequest -SessionVariable 'Session' "https://www.microsoft.com/en-us/software-download/windows10ISO/"
|
||||
$script:SessionId = $r.ParsedHtml.IHTMLDocument3_GetElementById("session-id").Value
|
||||
if (-not $SessionId) {
|
||||
throw "Could not read Session ID"
|
||||
}
|
||||
Write-Host "Session ID: $SessionId"
|
||||
}
|
||||
catch {
|
||||
Write-Host $_.Exception.Message
|
||||
$UserInput = [System.Windows.MessageBox]::Show("Error: " + $_.Exception.Message, "Error", "OK", "Error")
|
||||
# TODO: Don't use exit but set a global and close the dialog gracefully
|
||||
exit 1
|
||||
}
|
||||
$script:WindowsReleaseTitle = Add-Title($WindowsVersion.SelectedValue.Version + " Release")
|
||||
$script:WindowsRelease = Add-Combo
|
||||
|
||||
$i = 0
|
||||
$array = @()
|
||||
foreach ($Version in $WindowsVersions[$WindowsVersion.SelectedValue.Index]) {
|
||||
if ($Version -is [array]) {
|
||||
$array += @(New-Object PsObject -Property @{ Release = $Version[0]; Index = $i })
|
||||
}
|
||||
$i++
|
||||
}
|
||||
$WindowsRelease.ItemsSource = $array
|
||||
$WindowsRelease.DisplayMemberPath = "Release"
|
||||
|
||||
$XMLGrid.AddChild($WindowsReleaseTitle)
|
||||
$XMLGrid.AddChild($WindowsRelease)
|
||||
$Confirm.IsEnabled = $True
|
||||
}
|
||||
|
||||
2 { # Windows Release selection => Populate Product Edition
|
||||
$WindowsRelease.IsEnabled = $False
|
||||
$ProductEditionTitle = Add-Title("Edition")
|
||||
$script:ProductEdition = Add-Combo
|
||||
|
||||
$array = @()
|
||||
foreach ($Release in $WindowsVersions[$WindowsVersion.SelectedValue.Index][$WindowsRelease.SelectedValue.Index])
|
||||
{
|
||||
if ($Release -is [array]) {
|
||||
$array += @(New-Object PsObject -Property @{ Edition = $Release[0]; Id = $Release[1] })
|
||||
}
|
||||
}
|
||||
$ProductEdition.ItemsSource = $array
|
||||
$ProductEdition.DisplayMemberPath = "Edition"
|
||||
|
||||
$XMLGrid.AddChild($ProductEditionTitle)
|
||||
$XMLGrid.AddChild($ProductEdition)
|
||||
}
|
||||
|
||||
3 { # Product Edition selection => Request and populate Languages
|
||||
$ProductEdition.IsEnabled = $False
|
||||
$Confirm.IsEnabled = $False
|
||||
$Confirm.Dispatcher.Invoke("Render", [Windows.Input.InputEventHandler] { $Confirm.UpdateLayout() }, $null, $null)
|
||||
$LanguageTitle = Add-Title("Language")
|
||||
$script:Language = Add-Combo
|
||||
# Get the Product Edition
|
||||
|
||||
$url = "https://www.microsoft.com/en-us/api/controls/contentinclude/html"
|
||||
$url += "?pageId=a8f8f489-4c7f-463a-9ca6-5cff94d8d041"
|
||||
$url += "&host=www.microsoft.com"
|
||||
$url += "&segments=software-download,windows10ISO"
|
||||
$url += "&query=&action=GetSkuInformationByProductEdition"
|
||||
$url += "&sessionId=" + $SessionId
|
||||
$url += "&productEditionId=" + $ProductEdition.SelectedValue.Id
|
||||
$url += "&sdVersion=2"
|
||||
|
||||
try {
|
||||
$r = Invoke-WebRequest -WebSession $Session $url
|
||||
$array = @()
|
||||
foreach ($var in $r.ParsedHtml.IHTMLDocument3_GetElementByID("product-languages")) {
|
||||
$json = $var.value | ConvertFrom-Json;
|
||||
if ($json) {
|
||||
$array += @(New-Object PsObject -Property @{ Language = $json.language; Id = $json.id })
|
||||
}
|
||||
}
|
||||
if ($array.Length -eq 0) {
|
||||
throw "Could not parse languages"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host $_.Exception.Message
|
||||
$UserInput = [System.Windows.MessageBox]::Show("Error: " + $_.Exception.Message, "Error", "OK", "Error")
|
||||
exit 3
|
||||
}
|
||||
$Language.ItemsSource = $array
|
||||
$Language.DisplayMemberPath = "Language"
|
||||
# TODO: Select language that matches current MUI settings
|
||||
$XMLGrid.AddChild($LanguageTitle)
|
||||
$XMLGrid.AddChild($Language)
|
||||
$Confirm.IsEnabled = $True
|
||||
}
|
||||
|
||||
4 { # Language selection => Request and populate Arch download links
|
||||
$Language.IsEnabled = $False
|
||||
$Confirm.IsEnabled = $False
|
||||
$Confirm.Dispatcher.Invoke("Render", [Windows.Input.InputEventHandler] { $Confirm.UpdateLayout() }, $null, $null)
|
||||
$ArchTitle = Add-Title("Architecture")
|
||||
$script:Arch = Add-Combo
|
||||
|
||||
$url = "https://www.microsoft.com/en-us/api/controls/contentinclude/html"
|
||||
$url += "?pageId=cfa9e580-a81e-4a4b-a846-7b21bf4e2e5b"
|
||||
$url += "&host=www.microsoft.com"
|
||||
$url += "&segments=software-download,windows10ISO"
|
||||
$url += "&query=&action=GetProductDownloadLinksBySku"
|
||||
$url += "&sessionId=" + $SessionId
|
||||
$url += "&skuId=" + $Language.SelectedValue.Id
|
||||
$url += "&language=" + $Language.SelectedValue.Language
|
||||
$url += "&sdVersion=2"
|
||||
|
||||
try {
|
||||
$r = Invoke-WebRequest -WebSession $Session $url
|
||||
$array = @()
|
||||
foreach ($var in $r.ParsedHtml.IHTMLDocument3_GetElementsByTagName("span") | Where-Object { $_.className -eq "product-download-type" }) {
|
||||
$Link = $var.ParentNode | Select -Expand href
|
||||
$Type = $var.innerText
|
||||
# Maybe Microsoft will provide ARM/ARM64 download links one day...
|
||||
if ($Type -like "*arm64*") {
|
||||
$Type = "Arm64"
|
||||
} elseif ($Type -like "*arm*") {
|
||||
$Type = "Arm"
|
||||
} elseif ($Type -like "*x64*") {
|
||||
$Type = "x64"
|
||||
} elseif ($Type -like "*x86*") {
|
||||
$Type = "x86"
|
||||
}
|
||||
$array += @(New-Object PsObject -Property @{ Type = $Type; Link = $Link })
|
||||
}
|
||||
if ($array.Length -eq 0) {
|
||||
throw "Could not fetch download links"
|
||||
Write-Host $r.ParsedHtml.body.innerText
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host $_.Exception.Message
|
||||
$UserInput = [System.Windows.MessageBox]::Show("Error: " + $_.Exception.Message, "Error", "OK", "Error")
|
||||
exit 4
|
||||
}
|
||||
# TODO: Select Arch that matches current host
|
||||
$Arch.ItemsSource = $array
|
||||
$Arch.DisplayMemberPath = "Type"
|
||||
$XMLGrid.AddChild($ArchTitle)
|
||||
$XMLGrid.AddChild($Arch)
|
||||
$Confirm.Content = "Download"
|
||||
$Confirm.IsEnabled = $True
|
||||
}
|
||||
|
||||
5 { # Arch selection => Return selected download link
|
||||
$Arch.IsEnabled = $False
|
||||
$Confirm.IsEnabled = $False
|
||||
Write-Host $Arch.SelectedValue.Link
|
||||
}
|
||||
}
|
||||
|
||||
if ($Stage -lt 5) {
|
||||
$XMLForm.Height += $dh;
|
||||
$Margin = $Confirm.Margin
|
||||
@@ -142,71 +311,19 @@ $Confirm.add_click({
|
||||
$Confirm.Margin = $Margin
|
||||
}
|
||||
|
||||
switch ($Stage) {
|
||||
1 {
|
||||
$WindowsReleaseTitle = Add-Title($WindowsVersion.SelectedItem + " Release")
|
||||
$script:WindowsRelease = Add-Combo
|
||||
for ($i = 0; $i -lt $WindowsVersions.Length; $i++) {
|
||||
if ($WindowsVersions[$i][0] -eq $WindowsVersion.SelectedItem) {
|
||||
$script:VersionIndex = $i
|
||||
}
|
||||
}
|
||||
for($i = 1; $i -lt $WindowsVersions[$VersionIndex].Length; $i++) {
|
||||
$WindowsRelease.Items.Add($WindowsVersions[$VersionIndex][$i][0])
|
||||
}
|
||||
$WindowsVersion.IsEnabled = $False;
|
||||
$XMLGrid.AddChild($WindowsReleaseTitle)
|
||||
$XMLGrid.AddChild($WindowsRelease)
|
||||
}
|
||||
2 {
|
||||
$ProductEditionTitle = Add-Title("Edition")
|
||||
$script:ProductEdition = Add-Combo
|
||||
for ($i = 1; $i -lt $WindowsVersions[$VersionIndex].Length; $i++) {
|
||||
if ($WindowsVersions[$VersionIndex][$i][0] -eq $WindowsRelease.SelectedItem) {
|
||||
$script:ReleaseIndex = $i
|
||||
}
|
||||
}
|
||||
for($i = 1; $i -lt $WindowsVersions[$VersionIndex][$ReleaseIndex].Length; $i++) {
|
||||
# Yeah, none of the examples to associate a value to a ComboBox entry in PS *actually* work
|
||||
$ProductEdition.Items.Add($WindowsVersions[$VersionIndex][$ReleaseIndex][$i][0])
|
||||
}
|
||||
$WindowsRelease.IsEnabled = $False
|
||||
$XMLGrid.AddChild($ProductEditionTitle)
|
||||
$XMLGrid.AddChild($ProductEdition)
|
||||
}
|
||||
3 {
|
||||
$LanguageTitle = Add-Title("Language")
|
||||
$script:Language = Add-Combo
|
||||
# At last, we can get the SKU
|
||||
for ($i = 1; $i -lt $WindowsVersions[$VersionIndex][$ReleaseIndex].Length; $i++) {
|
||||
if ($WindowsVersions[$VersionIndex][$ReleaseIndex][$i][0] -eq $ProductEdition.SelectedItem) {
|
||||
$script:Sku = $WindowsVersions[$VersionIndex][$ReleaseIndex][$i][1]
|
||||
Write-Host "SKU: $Sku"
|
||||
}
|
||||
}
|
||||
$Language.Items.Add("English")
|
||||
$Language.Items.Add("German")
|
||||
$Language.Items.Add("French")
|
||||
$ProductEdition.IsEnabled = $False
|
||||
$XMLGrid.AddChild($LanguageTitle)
|
||||
$XMLGrid.AddChild($Language)
|
||||
}
|
||||
4 {
|
||||
$ArchTitle = Add-Title("Architecture")
|
||||
$script:Arch = Add-Combo
|
||||
$Arch.Items.add("x64")
|
||||
$Arch.Items.add("x86")
|
||||
$Language.IsEnabled = $False
|
||||
$XMLGrid.AddChild($ArchTitle)
|
||||
$XMLGrid.AddChild($Arch)
|
||||
$Confirm.Content = "Download"
|
||||
}
|
||||
5 {
|
||||
$Arch.IsEnabled = $False
|
||||
$Confirm.IsEnabled = $False
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# Show XMLform
|
||||
# We need a job in the background to close the obnoxious Windows "Do you want to accept this cookie" alerts
|
||||
$CloseStuff = {
|
||||
while ($True) {
|
||||
# TODO: We need to get this string from urlmon.dll.mui
|
||||
Get-Process | Where-Object { $_.MainWindowTitle -match "Windows Security Warning" } | ForEach-Object { $_.CloseMainWindow() }
|
||||
Start-Sleep -Milliseconds 200
|
||||
}
|
||||
}
|
||||
$job = Start-Job -ScriptBlock $CloseStuff
|
||||
|
||||
# Display the dialog
|
||||
$null = $XMLForm.ShowDialog()
|
||||
|
||||
Stop-Job -Job $job
|
||||
|
Reference in New Issue
Block a user