mirror of
https://github.com/pbatard/Fido.git
synced 2025-09-16 22:28:02 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b7331f7873 | ||
![]() |
6160db3c66 | ||
![]() |
8b40c85d76 | ||
![]() |
f70836e6c1 | ||
![]() |
af17001505 | ||
![]() |
43adf47d5d | ||
![]() |
99f6f246b8 | ||
![]() |
36e9b4420c | ||
![]() |
6d630f83f2 |
810
Fido.ps1
810
Fido.ps1
@@ -1,6 +1,7 @@
|
||||
#
|
||||
# Fido v1.18 - Retail Windows ISO Downloader
|
||||
# Fido v1.22 - Retail Windows ISO Downloader
|
||||
# Copyright © 2019-2021 Pete Batard <pete@akeo.ie>
|
||||
# Command line support: Copyright © 2021 flx5
|
||||
# ConvertTo-ImageSource: Copyright © 2016 Chris Carter
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -31,17 +32,31 @@ param(
|
||||
# (Optional) Name of a pipe the download URL should be sent to.
|
||||
# If not provided, a browser window is opened instead.
|
||||
[string]$PipeName,
|
||||
# (Optional) Disable IE First Run Customize so that Invoke-WebRequest
|
||||
# doesn't throw an exception if the user has never launched IE.
|
||||
# Note that this requires the script to run elevated.
|
||||
[switch]$DisableFirstRunCustomize
|
||||
# (Optional) Specify Windows version (e.g. "Windows 10") [Toggles commandline mode]
|
||||
[string]$Win,
|
||||
# (Optional) Specify Windows release (e.g. "21H1") [Toggles commandline mode]
|
||||
[string]$Rel,
|
||||
# (Optional) Specify Windows edition (e.g. "Pro") [Toggles commandline mode]
|
||||
[string]$Ed,
|
||||
# (Optional) Specify Windows language [Toggles commandline mode]
|
||||
[string]$Lang,
|
||||
# (Optional) Specify Windows architecture [Toggles commandline mode]
|
||||
[string]$Arch,
|
||||
# (Optional) Only display the download URL [Toggles commandline mode]
|
||||
[switch]$GetUrl = $False,
|
||||
# (Optional) Increase verbosity
|
||||
[switch]$Verbose = $False
|
||||
)
|
||||
#endregion
|
||||
|
||||
try {
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
} catch {}
|
||||
Write-Host Please Wait...
|
||||
|
||||
$Cmd = $False
|
||||
if ($Win -or $Rel -or $Ed -or $Lang -or $Arch -or $GetUrl) {
|
||||
$Cmd = $True
|
||||
}
|
||||
|
||||
#region Assembly Types
|
||||
$code = @"
|
||||
@@ -63,14 +78,17 @@ $code = @"
|
||||
}
|
||||
"@
|
||||
|
||||
if ($host.version -ge "7.0") {
|
||||
Add-Type -MemberDefinition $code -Namespace Gui -UsingNamespace System.Runtime, System.IO, System.Text, System.Drawing, System.Globalization -ReferencedAssemblies System.Drawing.Common -Name Utils -ErrorAction Stop
|
||||
} else {
|
||||
Add-Type -MemberDefinition $code -Namespace Gui -UsingNamespace System.IO, System.Text, System.Drawing, System.Globalization -ReferencedAssemblies System.Drawing -Name Utils -ErrorAction Stop
|
||||
if (!$Cmd) {
|
||||
Write-Host Please Wait...
|
||||
if ($host.version -ge "7.0") {
|
||||
Add-Type -WarningAction Ignore -IgnoreWarnings -MemberDefinition $code -Namespace Gui -UsingNamespace System.Runtime, System.IO, System.Text, System.Drawing, System.Globalization -ReferencedAssemblies System.Drawing.Common -Name Utils -ErrorAction Stop
|
||||
} else {
|
||||
Add-Type -MemberDefinition $code -Namespace Gui -UsingNamespace System.IO, System.Text, System.Drawing, System.Globalization -ReferencedAssemblies System.Drawing -Name Utils -ErrorAction Stop
|
||||
}
|
||||
Add-Type -AssemblyName PresentationFramework
|
||||
# Hide the powershell window: https://stackoverflow.com/a/27992426/1069307
|
||||
[Gui.Utils]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0) | Out-Null
|
||||
}
|
||||
Add-Type -AssemblyName PresentationFramework
|
||||
# Hide the powershell window: https://stackoverflow.com/a/27992426/1069307
|
||||
[Gui.Utils]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0) | Out-Null
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
@@ -79,6 +97,12 @@ $ko = 0x20000
|
||||
$WindowsVersions = @(
|
||||
@(
|
||||
@("Windows 10", "Windows10ISO"),
|
||||
@(
|
||||
"21H1 (Build 19043.985 - 2021.05)",
|
||||
@("Windows 10 Home/Pro", 2033),
|
||||
@("Windows 10 Education", 2032),
|
||||
@("Windows 10 Home China ", ($zh + 2034))
|
||||
),
|
||||
@(
|
||||
"20H2 (Build 19042.631 - 2020.12)",
|
||||
@("Windows 10 Home/Pro", 1882),
|
||||
@@ -207,14 +231,59 @@ $WindowsVersions = @(
|
||||
@("Windows 8.1", "windows8ISO"),
|
||||
@(
|
||||
"Update 3 (build 9600)",
|
||||
@("Windows 8.1", 52),
|
||||
@("Windows 8.1 Standard", 52),
|
||||
@("Windows 8.1 N", 55)
|
||||
@("Windows 8.1 Single Language", 48),
|
||||
@("Windows 8.1 K", ($ko + 61)),
|
||||
@("Windows 8.1 KN", ($ko + 62))
|
||||
)
|
||||
),
|
||||
@(
|
||||
@("Windows 7", "WIN7"),
|
||||
@(
|
||||
"with SP1 (build 7601)",
|
||||
@("Windows 7 Ultimate", 0),
|
||||
@("Windows 7 Professional", 1),
|
||||
@("Windows 7 Home Premium", 2)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
$Windows7Versions = @(
|
||||
# 0: Windows 7 Ultimate
|
||||
@(
|
||||
# Need a dummy to prevent PS from coalescing single array entries
|
||||
@(""),
|
||||
@("English (US)", "en-us",
|
||||
@(
|
||||
@("x64", "https://download.microsoft.com/download/5/1/9/5195A765-3A41-4A72-87D8-200D897CBE21/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_ULTIMATE_x64FRE_en-us.iso"),
|
||||
@("x86", "https://download.microsoft.com/download/1/E/6/1E6B4803-DD2A-49DF-8468-69C0E6E36218/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_ULTIMATE_x86FRE_en-us.iso")
|
||||
)
|
||||
)
|
||||
),
|
||||
# 1: Windows 7 Profesional
|
||||
@(
|
||||
@(""),
|
||||
@("English (US)", "en-us",
|
||||
@(
|
||||
@("x64", "https://download.microsoft.com/download/0/6/3/06365375-C346-4D65-87C7-EE41F55F736B/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_PROFESSIONAL_x64FRE_en-us.iso"),
|
||||
@("x86", "https://download.microsoft.com/download/C/0/6/C067D0CD-3785-4727-898E-60DC3120BB14/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_PROFESSIONAL_x86FRE_en-us.iso")
|
||||
)
|
||||
)
|
||||
),
|
||||
# 2: Windows 7 Home Premium
|
||||
@(
|
||||
@(""),
|
||||
@("English (US)", "en-us",
|
||||
@(
|
||||
@("x64", "https://download.microsoft.com/download/E/A/8/EA804D86-C3DF-4719-9966-6A66C9306598/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_HOMEPREMIUM_x64FRE_en-us.iso"),
|
||||
@("x86", "https://download.microsoft.com/download/E/D/A/EDA6B508-7663-4E30-86F9-949932F443D0/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_HOMEPREMIUM_x86FRE_en-us.iso")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
)
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
@@ -316,7 +385,7 @@ function Add-Entry([int]$pos, [string]$Name, [array]$Items, [string]$DisplayName
|
||||
|
||||
function Refresh-Control([object]$Control)
|
||||
{
|
||||
$Control.Dispatcher.Invoke("Render", [Windows.Input.InputEventHandler] { $Continue.UpdateLayout() }, $null, $null)
|
||||
$Control.Dispatcher.Invoke("Render", [Windows.Input.InputEventHandler] { $Continue.UpdateLayout() }, $null, $null) | Out-Null
|
||||
}
|
||||
|
||||
function Send-Message([string]$PipeName, [string]$Message)
|
||||
@@ -405,11 +474,15 @@ function GetElementById([object]$Request, [string]$Id)
|
||||
function Error([string]$ErrorMessage)
|
||||
{
|
||||
Write-Host Error: $ErrorMessage
|
||||
$XMLForm.Title = $(Get-Translation("Error")) + ": " + $ErrorMessage
|
||||
Refresh-Control($XMLForm)
|
||||
$XMLGrid.Children[2 * $script:Stage + 1].IsEnabled = $True
|
||||
$UserInput = [System.Windows.MessageBox]::Show($XMLForm.Title, $(Get-Translation("Error")), "OK", "Error")
|
||||
$script:ExitCode = $script:Stage--
|
||||
if (!$Cmd) {
|
||||
$XMLForm.Title = $(Get-Translation("Error")) + ": " + $ErrorMessage
|
||||
Refresh-Control($XMLForm)
|
||||
$XMLGrid.Children[2 * $script:Stage + 1].IsEnabled = $True
|
||||
$UserInput = [System.Windows.MessageBox]::Show($XMLForm.Title, $(Get-Translation("Error")), "OK", "Error")
|
||||
$script:ExitCode = $script:Stage--
|
||||
} else {
|
||||
$script:ExitCode = 2
|
||||
}
|
||||
}
|
||||
|
||||
function Get-RandomDate()
|
||||
@@ -440,23 +513,34 @@ function Get-RandomDate()
|
||||
|
||||
#region Globals
|
||||
$ErrorActionPreference = "Stop"
|
||||
$dh = 58;
|
||||
$dh = 58
|
||||
$Stage = 0
|
||||
$SelectedIndex = 0
|
||||
$ltrm = ""
|
||||
if ($Cmd) {
|
||||
$ltrm = ""
|
||||
}
|
||||
$MaxStage = 4
|
||||
$SessionId = [guid]::NewGuid()
|
||||
$ExitCode = 100
|
||||
$Locale = "en-US"
|
||||
$DFRCKey = "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main\"
|
||||
$DFRCName = "DisableFirstRunCustomize"
|
||||
$DFRCAdded = $False
|
||||
$RequestData = @{}
|
||||
# This GUID applies to all visitors, regardless of their locale
|
||||
$RequestData["GetLangs"] = @("a8f8f489-4c7f-463a-9ca6-5cff94d8d041", "getskuinformationbyproductedition" )
|
||||
$RequestData["GetLinks"] = @("cfa9e580-a81e-4a4b-a846-7b21bf4e2e5b", "GetProductDownloadLinksBySku" )
|
||||
# This GUID applies to visitors of the en-US download page. Other locales may get a different GUID.
|
||||
$RequestData["GetLinks"] = @("a224afab-2097-4dfa-a2ba-463eb191a285", "GetProductDownloadLinksBySku" )
|
||||
# Create a semi-random Linux User-Agent string
|
||||
$FirefoxVersion = Get-Random -Minimum 30 -Maximum 60
|
||||
$FirefoxVersion = Get-Random -Minimum 50 -Maximum 90
|
||||
$FirefoxDate = Get-RandomDate
|
||||
$UserAgent = "Mozilla/5.0 (X11; Linux i586; rv:$FirefoxVersion.0) Gecko/$FirefoxDate Firefox/$FirefoxVersion.0"
|
||||
$Verbosity = 2
|
||||
if ($Cmd) {
|
||||
if ($GetUrl) {
|
||||
$Verbosity = 0
|
||||
} elseif (!$Verbose) {
|
||||
$Verbosity = 1
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
# Localization
|
||||
@@ -485,18 +569,358 @@ if ($PSVersionTable.PSVersion.Major -lt 3) {
|
||||
exit 102
|
||||
}
|
||||
|
||||
# If asked, disable IE's first run customize prompt as it interferes with Invoke-WebRequest
|
||||
if ($DisableFirstRunCustomize) {
|
||||
try {
|
||||
# Only create the key if it doesn't already exist
|
||||
Get-ItemProperty -Path $DFRCKey -Name $DFRCName
|
||||
} catch {
|
||||
if (-not (Test-Path $DFRCKey)) {
|
||||
New-Item -Path $DFRCKey -Force | Out-Null
|
||||
}
|
||||
Set-ItemProperty -Path $DFRCKey -Name $DFRCName -Value 1
|
||||
$DFRCAdded = $True
|
||||
# Convert a size in bytes to a human readable string
|
||||
function Size-To-Human-Readable([uint64]$size)
|
||||
{
|
||||
$suffix = "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
|
||||
$i = 0
|
||||
while ($size -gt 1kb) {
|
||||
$size = $size / 1kb
|
||||
$i++
|
||||
}
|
||||
"{0:N1} {1}" -f $size, $suffix[$i]
|
||||
}
|
||||
|
||||
# Check if the locale we want is available - Fall back to en-US otherwise
|
||||
function Check-Locale {
|
||||
try {
|
||||
$url = "https://www.microsoft.com/" + $QueryLocale + "/software-download/"
|
||||
if ($Verbosity -ge 2) {
|
||||
Write-Host Querying $url
|
||||
}
|
||||
Invoke-WebRequest -UseBasicParsing -MaximumRedirection 0 -UserAgent $UserAgent $url | Out-Null
|
||||
} catch {
|
||||
$script:QueryLocale = "en-US"
|
||||
}
|
||||
}
|
||||
|
||||
# Return an array of releases (e.g. 20H2, 21H1, ...) for the selected Windows version
|
||||
function Get-Windows-Releases([int]$SelectedVersion)
|
||||
{
|
||||
$i = 0
|
||||
$releases = @()
|
||||
foreach ($version in $WindowsVersions[$SelectedVersion]) {
|
||||
if (($i -ne 0) -and ($version -is [array])) {
|
||||
$releases += @(New-Object PsObject -Property @{ Release = $ltrm + $version[0].Replace(")", ")" + $ltrm); Index = $i })
|
||||
}
|
||||
$i++
|
||||
}
|
||||
return $releases
|
||||
}
|
||||
|
||||
# Return an array of editions (e.g. Home, Pro, etc) for the selected Windows release
|
||||
function Get-Windows-Editions([int]$SelectedVersion, [int]$SelectedRelease)
|
||||
{
|
||||
$editions = @()
|
||||
foreach ($release in $WindowsVersions[$SelectedVersion][$SelectedRelease])
|
||||
{
|
||||
if ($release -is [array]) {
|
||||
if (($release[1] -lt 0x10000) -or ($Locale.StartsWith("ko") -and ($release[1] -band $ko)) -or ($Locale.StartsWith("zh") -and ($release[1] -band $zh))) {
|
||||
$editions += @(New-Object PsObject -Property @{ Edition = $release[0]; Id = $($release[1] -band 0xFFFF) })
|
||||
}
|
||||
}
|
||||
}
|
||||
return $editions
|
||||
}
|
||||
|
||||
# Return an array of languages for the selected edition
|
||||
function Get-Windows-Languages([int]$SelectedVersion, [int]$SelectedEdition)
|
||||
{
|
||||
$languages = @()
|
||||
$i = 0;
|
||||
if ($WindowsVersions[$SelectedVersion][0][1] -eq "WIN7") {
|
||||
foreach ($entry in $Windows7Versions[$SelectedEdition]) {
|
||||
if ($entry[0] -ne "") {
|
||||
$languages += @(New-Object PsObject -Property @{ DisplayLanguage = $entry[0]; Language = $entry[1]; Id = $i })
|
||||
}
|
||||
$i++
|
||||
}
|
||||
} else {
|
||||
$url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
|
||||
$url += "?pageId=" + $RequestData["GetLangs"][0]
|
||||
$url += "&host=www.microsoft.com"
|
||||
$url += "&segments=software-download," + $WindowsVersions[$SelectedVersion][0][1]
|
||||
$url += "&query=&action=" + $RequestData["GetLangs"][1]
|
||||
$url += "&sessionId=" + $SessionId
|
||||
$url += "&productEditionId=" + [Math]::Abs($SelectedEdition)
|
||||
$url += "&sdVersion=2"
|
||||
if ($Verbosity -ge 2) {
|
||||
Write-Host Querying $url
|
||||
}
|
||||
|
||||
$script:SelectedIndex = 0
|
||||
try {
|
||||
$r = Invoke-WebRequest -UseBasicParsing -UserAgent $UserAgent -SessionVariable "Session" $url
|
||||
if ($r -match "errorModalMessage") {
|
||||
Throw-Error -Req $r -Alt "Could not retrieve languages from server"
|
||||
}
|
||||
$pattern = '(?s)<select id="product-languages">(.*)?</select>'
|
||||
$html = [regex]::Match($r, $pattern).Groups[1].Value
|
||||
# Go through an XML conversion to keep all PowerShells happy...
|
||||
$html = $html.Replace("selected value", "value")
|
||||
$html = "<options>" + $html + "</options>"
|
||||
$xml = [xml]$html
|
||||
foreach ($var in $xml.options.option) {
|
||||
$json = $var.value | ConvertFrom-Json;
|
||||
if ($json) {
|
||||
$languages += @(New-Object PsObject -Property @{ DisplayLanguage = $var.InnerText; Language = $json.language; Id = $json.id })
|
||||
if (Select-Language($json.language)) {
|
||||
$script:SelectedIndex = $i
|
||||
}
|
||||
$i++
|
||||
}
|
||||
}
|
||||
if ($languages.Length -eq 0) {
|
||||
Throw-Error -Req $r -Alt "Could not parse languages"
|
||||
}
|
||||
} catch {
|
||||
Error($_.Exception.Message)
|
||||
return @()
|
||||
}
|
||||
}
|
||||
return $languages
|
||||
}
|
||||
|
||||
# Return an array of download links for each supported arch
|
||||
function Get-Windows-Download-Links([int]$SelectedVersion, [int]$SelectedEdition, [string]$SkuId, [string]$LanguageName)
|
||||
{
|
||||
$links = @()
|
||||
if ($WindowsVersions[$SelectedVersion][0][1] -eq "WIN7") {
|
||||
foreach ($Version in $Windows7Versions[$SelectedEdition][$SkuId][2]) {
|
||||
$links += @(New-Object PsObject -Property @{ Type = $Version[0]; Link = $Version[1] })
|
||||
}
|
||||
} else {
|
||||
$url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
|
||||
$url += "?pageId=" + $RequestData["GetLinks"][0]
|
||||
$url += "&host=www.microsoft.com"
|
||||
$url += "&segments=software-download," + $WindowsVersions[$SelectedVersion][0][1]
|
||||
$url += "&query=&action=" + $RequestData["GetLinks"][1]
|
||||
$url += "&sessionId=" + $SessionId
|
||||
$url += "&skuId=" + $SkuId
|
||||
$url += "&language=" + $LanguageName
|
||||
$url += "&sdVersion=2"
|
||||
if ($Verbosity -ge 2) {
|
||||
Write-Host Querying $url
|
||||
}
|
||||
|
||||
$i = 0
|
||||
$script:SelectedIndex = 0
|
||||
|
||||
try {
|
||||
$Is64 = [Environment]::Is64BitOperatingSystem
|
||||
$r = Invoke-WebRequest -Method Post -UseBasicParsing -UserAgent $UserAgent -WebSession $Session $url
|
||||
if ($r -match "errorModalMessage") {
|
||||
Throw-Error -Req $r -Alt "Could not retrieve architectures from server"
|
||||
}
|
||||
$pattern = '(?s)(<input.*?></input>)'
|
||||
ForEach-Object { [regex]::Matches($r, $pattern) } | ForEach-Object { $html += $_.Groups[1].value }
|
||||
# Need to fix the HTML and JSON data so that it is well-formed
|
||||
$html = $html.Replace("class=product-download-hidden", "")
|
||||
$html = $html.Replace("type=hidden", "")
|
||||
$html = $html.Replace(" ", " ")
|
||||
$html = $html.Replace("IsoX86", ""x86"")
|
||||
$html = $html.Replace("IsoX64", ""x64"")
|
||||
$html = "<inputs>" + $html + "</inputs>"
|
||||
$xml = [xml]$html
|
||||
foreach ($var in $xml.inputs.input) {
|
||||
$json = $var.value | ConvertFrom-Json;
|
||||
if ($json) {
|
||||
if (($Is64 -and $json.DownloadType -eq "x64") -or (-not $Is64 -and $json.DownloadType -eq "x86")) {
|
||||
$script:SelectedIndex = $i
|
||||
}
|
||||
$links += @(New-Object PsObject -Property @{ Type = $json.DownloadType; Link = $json.Uri })
|
||||
$i++
|
||||
}
|
||||
}
|
||||
if ($links.Length -eq 0) {
|
||||
Throw-Error -Req $r -Alt "Could not retrieve ISO download links"
|
||||
}
|
||||
} catch {
|
||||
Error($_.Exception.Message)
|
||||
return @()
|
||||
}
|
||||
}
|
||||
return $links
|
||||
}
|
||||
|
||||
# Process the download URL by either sending it through the pipe or by opening the browser
|
||||
function Process-Download-Link([string]$Url)
|
||||
{
|
||||
try {
|
||||
if ($PipeName -and -not $Check.IsChecked) {
|
||||
Send-Message -PipeName $PipeName -Message $Url
|
||||
} else {
|
||||
if ($Cmd) {
|
||||
$pattern = '.*\/(.*\.iso).*'
|
||||
$File = [regex]::Match($Url, $pattern).Groups[1].Value
|
||||
$Size = Size-To-Human-Readable (Invoke-WebRequest -UseBasicParsing -Uri $Url -Method Head).Headers.'Content-Length'
|
||||
Write-Host "Downloading '$File' ($Size)..."
|
||||
Invoke-WebRequest -UseBasicParsing -Uri $Url -OutFile $File
|
||||
} else {
|
||||
Write-Host Download Link: $Url
|
||||
Start-Process -FilePath $Url
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Error($_.Exception.Message)
|
||||
return 404
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
if ($Cmd) {
|
||||
$winVersionId = $null
|
||||
$winReleaseId = $null
|
||||
$winEditionId = $null
|
||||
$winLanguageId = $null
|
||||
$winLanguageName = $null
|
||||
$winLink = $null
|
||||
|
||||
$i = 0
|
||||
$Selected = ""
|
||||
if ($Win -eq "List") {
|
||||
Write-Host "Please select a Windows Version (-Win):"
|
||||
}
|
||||
foreach($version in $WindowsVersions) {
|
||||
if ($Win -eq "List") {
|
||||
Write-Host " -" $version[0][0]
|
||||
} elseif ($version[0][0] -match $Win) {
|
||||
$Selected += $version[0][0]
|
||||
$winVersionId = $i
|
||||
break;
|
||||
}
|
||||
$i++
|
||||
}
|
||||
if ($winVersionId -eq $null) {
|
||||
if ($Win -ne "List") {
|
||||
Write-Host "Invalid Windows version provided."
|
||||
Write-Host "Use '-Win List' for a list of available Windows versions."
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Windows Version selection
|
||||
$releases = Get-Windows-Releases $winVersionId
|
||||
if ($Rel -eq "List") {
|
||||
Write-Host "Please select a Windows Release (-Rel) for ${Selected} (or use 'Latest' for most recent):"
|
||||
}
|
||||
foreach ($release in $releases) {
|
||||
if ($Rel -eq "List") {
|
||||
Write-Host " -" $release.Release
|
||||
} elseif (!$Rel -or $release.Release.StartsWith($Rel) -or $Rel -eq "Latest") {
|
||||
if (!$Rel -and $Verbosity -ge 1) {
|
||||
Write-Host "No release specified (-Rel). Defaulting to '$($release.Release)'."
|
||||
}
|
||||
$Selected += " " + $release.Release
|
||||
$winReleaseId = $release.Index
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($winReleaseId -eq $null) {
|
||||
if ($Rel -ne "List") {
|
||||
Write-Host "Invalid Windows release provided."
|
||||
Write-Host "Use '-Rel List' for a list of available $Selected releases or '-Rel Latest' for latest."
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Windows Release selection => Populate Product Edition
|
||||
$editions = Get-Windows-Editions $winVersionId $winReleaseId
|
||||
if ($Ed -eq "List") {
|
||||
Write-Host "Please select a Windows Edition (-Ed) for ${Selected}:"
|
||||
}
|
||||
foreach($edition in $editions) {
|
||||
if ($Ed -eq "List") {
|
||||
Write-Host " -" $edition.Edition
|
||||
} elseif (!$Ed -or $edition.Edition -match $Ed) {
|
||||
if (!$Ed -and $Verbosity -ge 1) {
|
||||
Write-Host "No edition specified (-Ed). Defaulting to '$($edition.Edition)'."
|
||||
}
|
||||
$Selected += "," + $edition.Edition -replace "Windows [0-9\.]*", ""
|
||||
$winEditionId = $edition.Id
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($winEditionId -eq $null) {
|
||||
if ($Ed -ne "List") {
|
||||
Write-Host "Invalid Windows edition provided."
|
||||
Write-Host "Use '-Ed List' for a list of available editions or remove the -Ed parameter to use default."
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Product Edition selection => Request and populate Languages
|
||||
$languages = Get-Windows-Languages $winVersionId $winEditionId
|
||||
if (!$languages) {
|
||||
exit 3
|
||||
}
|
||||
if ($Lang -eq "List") {
|
||||
Write-Host "Please select a Language (-Lang) for ${Selected}:"
|
||||
}
|
||||
$i = 0
|
||||
foreach ($language in $languages) {
|
||||
if ($Lang -eq "List") {
|
||||
Write-Host " -" $language.Language
|
||||
} elseif ((!$Lang -and $script:SelectedIndex -eq $i) -or ($Lang -and $language.Language -match $Lang)) {
|
||||
if (!$Lang -and $Verbosity -ge 1) {
|
||||
Write-Host "No language specified (-Lang). Defaulting to '$($language.Language)'."
|
||||
}
|
||||
$Selected += ", " + $language.Language
|
||||
$winLanguageId = $language.Id
|
||||
$winLanguageName = $language.Language
|
||||
break;
|
||||
}
|
||||
$i++
|
||||
}
|
||||
if ($winLanguageId -eq $null -or $winLanguageName -eq $null) {
|
||||
if ($Lang -ne "List") {
|
||||
Write-Host "Invalid Windows language provided."
|
||||
Write-Host "Use '-Lang List' for a list of available languages or remove the option to use system default."
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Language selection => Request and populate Arch download links
|
||||
$links = Get-Windows-Download-Links $winVersionId $winEditionId $winLanguageId $winLanguageName
|
||||
if (!$links) {
|
||||
exit 3
|
||||
}
|
||||
if ($Arch -eq "List") {
|
||||
Write-Host "Please select an Architecture (-Arch) for ${Selected}:"
|
||||
}
|
||||
$i = 0
|
||||
foreach ($link in $links) {
|
||||
if ($Arch -eq "List") {
|
||||
Write-Host " -" $link.Type
|
||||
} elseif ((!$Arch -and $script:SelectedIndex -eq $i) -or ($Arch -and $link.Type -match $Arch)) {
|
||||
if (!$Arch -and $Verbosity -ge 1) {
|
||||
Write-Host "No architecture specified (-Arch). Defaulting to '$($link.Type)'."
|
||||
}
|
||||
$Selected += ", " + $link.Type
|
||||
$winLink = $link
|
||||
break;
|
||||
}
|
||||
$i++
|
||||
}
|
||||
if ($winLink -eq $null) {
|
||||
if ($Arch -ne "List") {
|
||||
Write-Host "Invalid Windows architecture provided."
|
||||
Write-Host "Use '-Arch List' for a list of available architectures or remove the option to use system default."
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Arch selection => Return selected download link
|
||||
if ($GetUrl) {
|
||||
Write-Host $winLink.Link
|
||||
$ExitCode = 0
|
||||
} else {
|
||||
Write-Host "Selected: $Selected"
|
||||
$ExitCode = Process-Download-Link $winLink.Link
|
||||
}
|
||||
|
||||
# Clean up & exit
|
||||
exit $ExitCode
|
||||
}
|
||||
|
||||
# Form creation
|
||||
@@ -508,7 +932,7 @@ if ($Icon) {
|
||||
} else {
|
||||
$XMLForm.Icon = [Gui.Utils]::ExtractIcon("shell32.dll", -41, $true) | ConvertTo-ImageSource
|
||||
}
|
||||
if ($Locale.StartsWith("ar") -or $Locale.StartsWith("fa") -or $Locale.StartsWith("he")) {
|
||||
if ($Locale.StartsWith("ar") -or $Locale.StartsWith("fa") -or $Locale.StartsWith("he")) {
|
||||
$XMLForm.FlowDirection = "RightToLeft"
|
||||
}
|
||||
$WindowsVersionTitle.Text = Get-Translation("Version")
|
||||
@@ -517,12 +941,12 @@ $Back.Content = Get-Translation("Close")
|
||||
|
||||
# Populate the Windows versions
|
||||
$i = 0
|
||||
$array = @()
|
||||
foreach($Version in $WindowsVersions) {
|
||||
$array += @(New-Object PsObject -Property @{ Version = $Version[0][0]; PageType = $Version[0][1]; Index = $i })
|
||||
$versions = @()
|
||||
foreach($version in $WindowsVersions) {
|
||||
$versions += @(New-Object PsObject -Property @{ Version = $version[0][0]; PageType = $version[0][1]; Index = $i })
|
||||
$i++
|
||||
}
|
||||
$WindowsVersion.ItemsSource = $array
|
||||
$WindowsVersion.ItemsSource = $versions
|
||||
$WindowsVersion.DisplayMemberPath = "Version"
|
||||
|
||||
# Button Action
|
||||
@@ -539,147 +963,38 @@ $Continue.add_click({
|
||||
1 { # Windows Version selection
|
||||
$XMLForm.Title = Get-Translation($English[12])
|
||||
Refresh-Control($XMLForm)
|
||||
# Check if the locale we want is available - Fall back to en-US otherwise
|
||||
try {
|
||||
$url = "https://www.microsoft.com/" + $QueryLocale + "/software-download/"
|
||||
Write-Host Querying $url
|
||||
Invoke-WebRequest -UseBasicParsing -MaximumRedirection 0 -UserAgent $UserAgent $url | Out-Null
|
||||
} catch {
|
||||
$script:QueryLocale = "en-US"
|
||||
}
|
||||
|
||||
$i = 0
|
||||
$array = @()
|
||||
foreach ($Version in $WindowsVersions[$WindowsVersion.SelectedValue.Index]) {
|
||||
if (($i -ne 0) -and ($Version -is [array])) {
|
||||
$array += @(New-Object PsObject -Property @{ Release = $ltrm + $Version[0].Replace(")", ")" + $ltrm); Index = $i })
|
||||
}
|
||||
$i++
|
||||
}
|
||||
|
||||
$script:WindowsRelease = Add-Entry $Stage "Release" $array
|
||||
Check-Locale
|
||||
$releases = Get-Windows-Releases $WindowsVersion.SelectedValue.Index
|
||||
$script:WindowsRelease = Add-Entry $Stage "Release" $releases
|
||||
$Back.Content = Get-Translation($English[8])
|
||||
$XMLForm.Title = $AppTitle
|
||||
}
|
||||
|
||||
2 { # Windows Release selection => Populate Product Edition
|
||||
$array = @()
|
||||
foreach ($Release in $WindowsVersions[$WindowsVersion.SelectedValue.Index][$WindowsRelease.SelectedValue.Index])
|
||||
{
|
||||
if ($Release -is [array]) {
|
||||
if (($Release[1] -lt 0x10000) -or ($Locale.StartsWith("ko") -and ($Release[1] -band $ko)) -or ($Locale.StartsWith("zh") -and ($Release[1] -band $zh))) {
|
||||
$array += @(New-Object PsObject -Property @{ Edition = $Release[0]; Id = $($Release[1] -band 0xFFFF) })
|
||||
}
|
||||
}
|
||||
}
|
||||
$script:ProductEdition = Add-Entry $Stage "Edition" $array
|
||||
$editions = Get-Windows-Editions $WindowsVersion.SelectedValue.Index $WindowsRelease.SelectedValue.Index
|
||||
$script:ProductEdition = Add-Entry $Stage "Edition" $editions
|
||||
}
|
||||
|
||||
3 { # Product Edition selection => Request and populate Languages
|
||||
3 { # Product Edition selection => Request and populate languages
|
||||
$XMLForm.Title = Get-Translation($English[12])
|
||||
Refresh-Control($XMLForm)
|
||||
$url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
|
||||
$url += "?pageId=" + $RequestData["GetLangs"][0]
|
||||
$url += "&host=www.microsoft.com"
|
||||
$url += "&segments=software-download," + $WindowsVersion.SelectedValue.PageType
|
||||
$url += "&query=&action=" + $RequestData["GetLangs"][1]
|
||||
$url += "&sessionId=" + $SessionId
|
||||
$url += "&productEditionId=" + [Math]::Abs($ProductEdition.SelectedValue.Id)
|
||||
$url += "&sdVersion=2"
|
||||
Write-Host Querying $url
|
||||
|
||||
$array = @()
|
||||
$i = 0
|
||||
$SelectedIndex = 0
|
||||
try {
|
||||
$r = Invoke-WebRequest -UserAgent $UserAgent -SessionVariable "Session" $url
|
||||
# Go through an XML conversion to keep all PowerShells happy...
|
||||
if (-not $($r.AllElements | ? {$_.id -eq "product-languages"})) {
|
||||
if ($host.version -ge "7.0") {
|
||||
throw "This PowerShell version can not parse HTML"
|
||||
} else {
|
||||
throw "Unexpected server response"
|
||||
}
|
||||
}
|
||||
$html = $($r.AllElements | ? {$_.id -eq "product-languages"}).InnerHTML
|
||||
$html = $html.Replace("selected value", "value")
|
||||
$html = $html.Replace("&", "&")
|
||||
$html = "<options>" + $html + "</options>"
|
||||
$xml = [xml]$html
|
||||
foreach ($var in $xml.options.option) {
|
||||
$json = $var.value | ConvertFrom-Json;
|
||||
if ($json) {
|
||||
$array += @(New-Object PsObject -Property @{ DisplayLanguage = $var.InnerText; Language = $json.language; Id = $json.id })
|
||||
if (Select-Language($json.language)) {
|
||||
$SelectedIndex = $i
|
||||
}
|
||||
$i++
|
||||
}
|
||||
}
|
||||
if ($array.Length -eq 0) {
|
||||
Throw-Error -Req $r -Alt "Could not parse languages"
|
||||
}
|
||||
} catch {
|
||||
Error($_.Exception.Message)
|
||||
$languages = Get-Windows-Languages $WindowsVersion.SelectedValue.Index $ProductEdition.SelectedValue.Id
|
||||
if ($languages.Length -eq 0) {
|
||||
break
|
||||
}
|
||||
$script:Language = Add-Entry $Stage "Language" $array "DisplayLanguage"
|
||||
$Language.SelectedIndex = $SelectedIndex
|
||||
$script:Language = Add-Entry $Stage "Language" $languages "DisplayLanguage"
|
||||
$Language.SelectedIndex = $script:SelectedIndex
|
||||
$XMLForm.Title = $AppTitle
|
||||
}
|
||||
|
||||
4 { # Language selection => Request and populate Arch download links
|
||||
$XMLForm.Title = Get-Translation($English[12])
|
||||
Refresh-Control($XMLForm)
|
||||
$url = "https://www.microsoft.com/" + $QueryLocale + "/api/controls/contentinclude/html"
|
||||
$url += "?pageId=" + $RequestData["GetLinks"][0]
|
||||
$url += "&host=www.microsoft.com"
|
||||
$url += "&segments=software-download," + $WindowsVersion.SelectedValue.PageType
|
||||
$url += "&query=&action=" + $RequestData["GetLinks"][1]
|
||||
$url += "&sessionId=" + $SessionId
|
||||
$url += "&skuId=" + $Language.SelectedValue.Id
|
||||
$url += "&language=" + $Language.SelectedValue.Language
|
||||
$url += "&sdVersion=2"
|
||||
Write-Host Querying $url
|
||||
|
||||
$i = 0
|
||||
$SelectedIndex = 0
|
||||
$array = @()
|
||||
try {
|
||||
$Is64 = [Environment]::Is64BitOperatingSystem
|
||||
$r = Invoke-WebRequest -UserAgent $UserAgent -WebSession $Session $url
|
||||
if (-not $($r.AllElements | ? {$_.id -eq "expiration-time"})) {
|
||||
Throw-Error -Req $r -Alt Get-Translation($English[14])
|
||||
}
|
||||
$html = $($r.AllElements | ? {$_.tagname -eq "input"}).outerHTML
|
||||
# Need to fix the HTML and JSON data so that it is well-formed
|
||||
$html = $html.Replace("class=product-download-hidden", "")
|
||||
$html = $html.Replace("type=hidden", "")
|
||||
$html = $html.Replace(">", "/>")
|
||||
$html = $html.Replace(" ", " ")
|
||||
$html = $html.Replace("IsoX86", """x86""")
|
||||
$html = $html.Replace("IsoX64", """x64""")
|
||||
$html = "<inputs>" + $html + "</inputs>"
|
||||
$xml = [xml]$html
|
||||
foreach ($var in $xml.inputs.input) {
|
||||
$json = $var.value | ConvertFrom-Json;
|
||||
if ($json) {
|
||||
if (($Is64 -and $json.DownloadType -eq "x64") -or (-not $Is64 -and $json.DownloadType -eq "x86")) {
|
||||
$SelectedIndex = $i
|
||||
}
|
||||
$array += @(New-Object PsObject -Property @{ Type = $json.DownloadType; Link = $json.Uri })
|
||||
$i++
|
||||
}
|
||||
}
|
||||
if ($array.Length -eq 0) {
|
||||
Throw-Error -Req $r -Alt "Could not retrieve ISO download links"
|
||||
}
|
||||
} catch {
|
||||
Error($_.Exception.Message)
|
||||
$links = Get-Windows-Download-Links $WindowsVersion.SelectedValue.Index $ProductEdition.SelectedValue.Id $Language.SelectedValue.Id $Language.SelectedValue.Language
|
||||
if ($links.Length -eq 0) {
|
||||
break
|
||||
}
|
||||
|
||||
$script:Arch = Add-Entry $Stage "Architecture" $array "Type"
|
||||
$script:Architecture = Add-Entry $Stage "Architecture" $links "Type"
|
||||
if ($PipeName) {
|
||||
$XMLForm.Height += $dh / 2;
|
||||
$Margin = $Continue.Margin
|
||||
@@ -695,19 +1010,13 @@ $Continue.add_click({
|
||||
$Check.Content = Get-Translation($English[13])
|
||||
$Check.Visibility = "Visible"
|
||||
}
|
||||
$Arch.SelectedIndex = $SelectedIndex
|
||||
$Architecture.SelectedIndex = $script:SelectedIndex
|
||||
$Continue.Content = Get-Translation("Download")
|
||||
$XMLForm.Title = $AppTitle
|
||||
}
|
||||
|
||||
5 { # Arch selection => Return selected download link
|
||||
if ($PipeName -and -not $Check.IsChecked) {
|
||||
Send-Message -PipeName $PipeName -Message $Arch.SelectedValue.Link
|
||||
} else {
|
||||
Write-Host Download Link: $Arch.SelectedValue.Link
|
||||
Start-Process -FilePath $Arch.SelectedValue.Link
|
||||
}
|
||||
$script:ExitCode = 0
|
||||
$script:ExitCode = Process-Download-Link $Architecture.SelectedValue.Link
|
||||
$XMLForm.Close()
|
||||
}
|
||||
}
|
||||
@@ -752,7 +1061,158 @@ $XMLForm.Add_Loaded( { $XMLForm.Activate() } )
|
||||
$XMLForm.ShowDialog() | Out-Null
|
||||
|
||||
# Clean up & exit
|
||||
if ($DFRCAdded) {
|
||||
Remove-ItemProperty -Path $DFRCKey -Name $DFRCName
|
||||
}
|
||||
exit $ExitCode
|
||||
|
||||
# SIG # Begin signature block
|
||||
# MIIcQwYJKoZIhvcNAQcCoIIcNDCCHDACAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAmntMmTpBFNzz7
|
||||
# Fdr1eV8O1VgbNVoFgkOjlsq1UXZyy6CCCy4wggVGMIIELqADAgECAhAkaSZj72wM
|
||||
# Cjsjz6MQw2SbMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAkdCMRswGQYDVQQI
|
||||
# ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoT
|
||||
# EUNPTU9ETyBDQSBMaW1pdGVkMSMwIQYDVQQDExpDT01PRE8gUlNBIENvZGUgU2ln
|
||||
# bmluZyBDQTAeFw0xODAzMTYwMDAwMDBaFw0yMjAzMTYyMzU5NTlaMIGTMQswCQYD
|
||||
# VQQGEwJJRTERMA8GA1UEEQwIRjkyIEQ2NjcxFDASBgNVBAgMC0NvLiBEb25lZ2Fs
|
||||
# MRAwDgYDVQQHDAdNaWxmb3JkMRUwEwYDVQQJDAwyNCBHcmV5IFJvY2sxGDAWBgNV
|
||||
# BAoMD0FrZW8gQ29uc3VsdGluZzEYMBYGA1UEAwwPQWtlbyBDb25zdWx0aW5nMIIB
|
||||
# IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAucIiMwsQe8seN3s519ZbhFfX
|
||||
# XswzuieRtmXeB9nVlsU2s5UFZ3pdNSh9upBdHB08LC0zCiowvXxljlKrxVEP+sxZ
|
||||
# 54AGNqcGdPDyKFVugkFXOLmVo0YI2HQ1H6Sig7ML229vAeXoOqze0xZfBJ3L5Z0S
|
||||
# rs/Tr+X1pN/UcjiIrT2ka3wXi/Rw/qUPwfAEpzHLPEgGT3z04vfb13Y2GZ6tR5LY
|
||||
# 7g2jFWZVB4AeeH0oVoPoHFjWWzh2sutbeWDV784MrMEvokFFBalQSq2Hdjbz0wCw
|
||||
# WvlnJXpAwexdLWsUuDNqihK+u5TqCa0s5wQa9g7j4Lnh/gE2gT82ZpvG4FWpQQID
|
||||
# AQABo4IBqTCCAaUwHwYDVR0jBBgwFoAUKZFg/4pN+uv5pmq4z/nmS71JzhIwHQYD
|
||||
# VR0OBBYEFHqk0HHXrPqMfyjl4r9RvfCV36uOMA4GA1UdDwEB/wQEAwIHgDAMBgNV
|
||||
# HRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIE
|
||||
# EDBGBgNVHSAEPzA9MDsGDCsGAQQBsjEBAgEDAjArMCkGCCsGAQUFBwIBFh1odHRw
|
||||
# czovL3NlY3VyZS5jb21vZG8ubmV0L0NQUzBDBgNVHR8EPDA6MDigNqA0hjJodHRw
|
||||
# Oi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDb2RlU2lnbmluZ0NBLmNybDB0
|
||||
# BggrBgEFBQcBAQRoMGYwPgYIKwYBBQUHMAKGMmh0dHA6Ly9jcnQuY29tb2RvY2Eu
|
||||
# Y29tL0NPTU9ET1JTQUNvZGVTaWduaW5nQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRw
|
||||
# Oi8vb2NzcC5jb21vZG9jYS5jb20wGgYDVR0RBBMwEYEPc3VwcG9ydEBha2VvLmll
|
||||
# MA0GCSqGSIb3DQEBCwUAA4IBAQA3dG72Ftdt3/AXoxMDovsxatdFghcKHjl01+8x
|
||||
# 6iguabtan9Lqz2yulzj4px2KCUV64VPhRytaS15YHZDJH7Q9BlTvcgNpSujs3fkQ
|
||||
# KdSmHs+MrNMetpAT6WH185J1z/3rRLc/LpESc6tipocAkA7uPualGIkBJNFEwqiT
|
||||
# aTjR3h3zGZs2aEJJ2X8DgBEg9zgZNUzr6zsprHyCODAtmO89owAywKQbu/ZczsVE
|
||||
# mPJKgJ511BZlyTLW5elvB17QX95vqoit0ZGhbMTHKtJxojyUZZC7Y+cV6E6/HbQA
|
||||
# tvcFWa5BzljDyRC70uFeEPV8t6ine6ytd98BWaF13IB8jqYQMIIF4DCCA8igAwIB
|
||||
# AgIQLnyHzA6TSlL+lP0ct800rzANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UEBhMC
|
||||
# R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9y
|
||||
# ZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBS
|
||||
# U0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTMwNTA5MDAwMDAwWhcNMjgw
|
||||
# NTA4MjM1OTU5WjB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5j
|
||||
# aGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGlt
|
||||
# aXRlZDEjMCEGA1UEAxMaQ09NT0RPIFJTQSBDb2RlIFNpZ25pbmcgQ0EwggEiMA0G
|
||||
# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmmJBjd5E0f4rR3elnMRHrzB79MR2z
|
||||
# uWJXP5O8W+OfHiQyESdrvFGRp8+eniWzX4GoGA8dHiAwDvthe4YJs+P9omidHCyd
|
||||
# v3Lj5HWg5TUjjsmK7hoMZMfYQqF7tVIDSzqwjiNLS2PgIpQ3e9V5kAoUGFEs5v7B
|
||||
# EvAcP2FhCoyi3PbDMKrNKBh1SMF5WgjNu4xVjPfUdpA6M0ZQc5hc9IVKaw+A3V7W
|
||||
# vf2pL8Al9fl4141fEMJEVTyQPDFGy3CuB6kK46/BAW+QGiPiXzjbxghdR7ODQfAu
|
||||
# ADcUuRKqeZJSzYcPe9hiKaR+ML0btYxytEjy4+gh+V5MYnmLAgaff9ULAgMBAAGj
|
||||
# ggFRMIIBTTAfBgNVHSMEGDAWgBS7r34CPfqm8TyEjq3uOJjs2TIy1DAdBgNVHQ4E
|
||||
# FgQUKZFg/4pN+uv5pmq4z/nmS71JzhIwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB
|
||||
# /wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYDVR0gBAowCDAGBgRV
|
||||
# HSAAMEwGA1UdHwRFMEMwQaA/oD2GO2h0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NP
|
||||
# TU9ET1JTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMHEGCCsGAQUFBwEBBGUw
|
||||
# YzA7BggrBgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNB
|
||||
# QWRkVHJ1c3RDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2Nh
|
||||
# LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAAj8COcPu+Mo7id4MbU2x8U6ST6/COCwE
|
||||
# zMVjEasJY6+rotcCP8xvGcM91hoIlP8l2KmIpysQGuCbsQciGlEcOtTh6Qm/5iR0
|
||||
# rx57FjFuI+9UUS1SAuJ1CAVM8bdR4VEAxof2bO4QRHZXavHfWGshqknUfDdOvf+2
|
||||
# dVRAGDZXZxHNTwLk/vPa/HUX2+y392UJI0kfQ1eD6n4gd2HITfK7ZU2o94VFB696
|
||||
# aSdlkClAi997OlE5jKgfcHmtbUIgos8MbAOMTM1zB5TnWo46BLqioXwfy2M6FafU
|
||||
# FRunUkcyqfS/ZEfRqh9TTjIwc8Jvt3iCnVz/RrtrIh2IC/gbqjSm/Iz13X9ljIwx
|
||||
# VzHQNuxHoc/Li6jvHBhYxQZ3ykubUa9MCEp6j+KjUuKOjswm5LLY5TjCqO3GgZw1
|
||||
# a6lYYUoKl7RLQrZVnb6Z53BtWfhtKgx/GWBfDJqIbDCsUgmQFhv/K53b0CDKieoo
|
||||
# fjKOGd97SDMe12X4rsn4gxSTdn1k0I7OvjV9/3IxTZ+evR5sL6iPDAZQ+4wns3bJ
|
||||
# 9ObXwzTijIchhmH+v1V04SF3AwpobLvkyanmz1kl63zsRQ55ZmjoIs2475iFTZYR
|
||||
# PAmK0H+8KCgT+2rKVI2SXM3CZZgGns5IW9S1N5NGQXwH3c/6Q++6Z2H/fUnguzB9
|
||||
# XIDj5hY5S6cxghBrMIIQZwIBATCBkTB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMS
|
||||
# R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
|
||||
# T01PRE8gQ0EgTGltaXRlZDEjMCEGA1UEAxMaQ09NT0RPIFJTQSBDb2RlIFNpZ25p
|
||||
# bmcgQ0ECECRpJmPvbAwKOyPPoxDDZJswDQYJYIZIAWUDBAIBBQCgfDAQBgorBgEE
|
||||
# AYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3
|
||||
# AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQg3YrGMVQO6qoD6cPt
|
||||
# bS6JpG4LAHdwqpn65+mFIK20j68wDQYJKoZIhvcNAQEBBQAEggEAaOT1Mq29RraP
|
||||
# g8WgeT6dSzudY/U4rPQOa8PqYGOfs0aAbaqU5LNk9rJyHKmALvKxqUvqoFMtZIBl
|
||||
# wj9WK0rKjaEA0gNUsnhveZxUt84D3R7uDwxsU++5CHg0MWg1+2EGKpxAEhwcjXsJ
|
||||
# CNIKYH52N/bCL1A7b+1sA54InD7CmvW7iFzHOIMYBEnZHalL3pdJHHBZYn5/6FYO
|
||||
# eLpywxEmxAbvBrenDx0Q1YMSKT2yuNv7wkcnmiLAgWrF6mxOWMKPRxZ/PHn4Fmd4
|
||||
# 0a2lheONssR2PonYuz2cy8RGgdCIMOxVjKiAySyrO0rnDEtyUa4z8yRJ47bsyADp
|
||||
# 3GCPoTNZfKGCDiwwgg4oBgorBgEEAYI3AwMBMYIOGDCCDhQGCSqGSIb3DQEHAqCC
|
||||
# DgUwgg4BAgEDMQ0wCwYJYIZIAWUDBAIBMIH/BgsqhkiG9w0BCRABBKCB7wSB7DCB
|
||||
# 6QIBAQYLYIZIAYb4RQEHFwMwITAJBgUrDgMCGgUABBS6Tve1nOlSlyVopkBKK7nB
|
||||
# lrnrfwIVAI34GQCgDsf6NPlJCdRvrIILrKZUGA8yMDIxMDgxOTIwNDYwM1owAwIB
|
||||
# HqCBhqSBgzCBgDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBv
|
||||
# cmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEwLwYDVQQD
|
||||
# EyhTeW1hbnRlYyBTSEEyNTYgVGltZVN0YW1waW5nIFNpZ25lciAtIEczoIIKizCC
|
||||
# BTgwggQgoAMCAQICEHsFsdRJaFFE98mJ0pwZnRIwDQYJKoZIhvcNAQELBQAwgb0x
|
||||
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMW
|
||||
# VmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDIwMDggVmVyaVNp
|
||||
# Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE4MDYGA1UEAxMvVmVy
|
||||
# aVNpZ24gVW5pdmVyc2FsIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN
|
||||
# MTYwMTEyMDAwMDAwWhcNMzEwMTExMjM1OTU5WjB3MQswCQYDVQQGEwJVUzEdMBsG
|
||||
# A1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRy
|
||||
# dXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5bWFudGVjIFNIQTI1NiBUaW1lU3RhbXBp
|
||||
# bmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7WZ1ZVU+djHJd
|
||||
# GoGi61XzsAGtPHGsMo8Fa4aaJwAyl2pNyWQUSym7wtkpuS7sY7Phzz8LVpD4Yht+
|
||||
# 66YH4t5/Xm1AONSRBudBfHkcy8utG7/YlZHz8O5s+K2WOS5/wSe4eDnFhKXt7a+H
|
||||
# js6Nx23q0pi1Oh8eOZ3D9Jqo9IThxNF8ccYGKbQ/5IMNJsN7CD5N+Qq3M0n/yjvU
|
||||
# 9bKbS+GImRr1wOkzFNbfx4Dbke7+vJJXcnf0zajM/gn1kze+lYhqxdz0sUvUzugJ
|
||||
# kV+1hHk1inisGTKPI8EyQRtZDqk+scz51ivvt9jk1R1tETqS9pPJnONI7rtTDtQ2
|
||||
# l4Z4xaE3AgMBAAGjggF3MIIBczAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw
|
||||
# BgEB/wIBADBmBgNVHSAEXzBdMFsGC2CGSAGG+EUBBxcDMEwwIwYIKwYBBQUHAgEW
|
||||
# F2h0dHBzOi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkaF2h0dHBzOi8v
|
||||
# ZC5zeW1jYi5jb20vcnBhMC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0
|
||||
# cDovL3Muc3ltY2QuY29tMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9zLnN5bWNi
|
||||
# LmNvbS91bml2ZXJzYWwtcm9vdC5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwgwKAYD
|
||||
# VR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0yMDQ4LTMwHQYDVR0OBBYE
|
||||
# FK9j1sqjToVy4Ke8QfMpojh/gHViMB8GA1UdIwQYMBaAFLZ3+mlIR59TEtXC6gcy
|
||||
# dgfRlwcZMA0GCSqGSIb3DQEBCwUAA4IBAQB16rAt1TQZXDJF/g7h1E+meMFv1+rd
|
||||
# 3E/zociBiPenjxXmQCmt5l30otlWZIRxMCrdHmEXZiBWBpgZjV1x8viXvAn9HJFH
|
||||
# yeLojQP7zJAv1gpsTjPs1rSTyEyQY0g5QCHE3dZuiZg8tZiX6KkGtwnJj1NXQZAv
|
||||
# 4R5NTtzKEHhsQm7wtsX4YVxS9U72a433Snq+8839A9fZ9gOoD+NT9wp17MZ1Lqpm
|
||||
# hQSZt/gGV+HGDvbor9rsmxgfqrnjOgC/zoqUywHbnsc4uw9Sq9HjlANgCk2g/idt
|
||||
# FDL8P5dA4b+ZidvkORS92uTTw+orWrOVWFUEfcea7CMDjYUq0v+uqWGBMIIFSzCC
|
||||
# BDOgAwIBAgIQe9Tlr7rMBz+hASMEIkFNEjANBgkqhkiG9w0BAQsFADB3MQswCQYD
|
||||
# VQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsT
|
||||
# FlN5bWFudGVjIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMTH1N5bWFudGVjIFNIQTI1
|
||||
# NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMTcxMjIzMDAwMDAwWhcNMjkwMzIyMjM1OTU5
|
||||
# WjCBgDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9u
|
||||
# MR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEwLwYDVQQDEyhTeW1h
|
||||
# bnRlYyBTSEEyNTYgVGltZVN0YW1waW5nIFNpZ25lciAtIEczMIIBIjANBgkqhkiG
|
||||
# 9w0BAQEFAAOCAQ8AMIIBCgKCAQEArw6Kqvjcv2l7VBdxRwm9jTyB+HQVd2eQnP3e
|
||||
# TgKeS3b25TY+ZdUkIG0w+d0dg+k/J0ozTm0WiuSNQI0iqr6nCxvSB7Y8tRokKPgb
|
||||
# clE9yAmIJgg6+fpDI3VHcAyzX1uPCB1ySFdlTa8CPED39N0yOJM/5Sym81kjy4De
|
||||
# E035EMmqChhsVWFX0fECLMS1q/JsI9KfDQ8ZbK2FYmn9ToXBilIxq1vYyXRS41ds
|
||||
# Ir9Vf2/KBqs/SrcidmXs7DbylpWBJiz9u5iqATjTryVAmwlT8ClXhVhe6oVIQSGH
|
||||
# 5d600yaye0BTWHmOUjEGTZQDRcTOPAPstwDyOiLFtG/l77CKmwIDAQABo4IBxzCC
|
||||
# AcMwDAYDVR0TAQH/BAIwADBmBgNVHSAEXzBdMFsGC2CGSAGG+EUBBxcDMEwwIwYI
|
||||
# KwYBBQUHAgEWF2h0dHBzOi8vZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBka
|
||||
# F2h0dHBzOi8vZC5zeW1jYi5jb20vcnBhMEAGA1UdHwQ5MDcwNaAzoDGGL2h0dHA6
|
||||
# Ly90cy1jcmwud3Muc3ltYW50ZWMuY29tL3NoYTI1Ni10c3MtY2EuY3JsMBYGA1Ud
|
||||
# JQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDB3BggrBgEFBQcBAQRr
|
||||
# MGkwKgYIKwYBBQUHMAGGHmh0dHA6Ly90cy1vY3NwLndzLnN5bWFudGVjLmNvbTA7
|
||||
# BggrBgEFBQcwAoYvaHR0cDovL3RzLWFpYS53cy5zeW1hbnRlYy5jb20vc2hhMjU2
|
||||
# LXRzcy1jYS5jZXIwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y
|
||||
# MDQ4LTYwHQYDVR0OBBYEFKUTAamfhcwbbhYeXzsxqnk2AHsdMB8GA1UdIwQYMBaA
|
||||
# FK9j1sqjToVy4Ke8QfMpojh/gHViMA0GCSqGSIb3DQEBCwUAA4IBAQBGnq/wuKJf
|
||||
# oplIz6gnSyHNsrmmcnBjL+NVKXs5Rk7nfmUGWIu8V4qSDQjYELo2JPoKe/s702K/
|
||||
# SpQV5oLbilRt/yj+Z89xP+YzCdmiWRD0Hkr+Zcze1GvjUil1AEorpczLm+ipTfe0
|
||||
# F1mSQcO3P4bm9sB/RDxGXBda46Q71Wkm1SF94YBnfmKst04uFZrlnCOvWxHqcalB
|
||||
# +Q15OKmhDc+0sdo+mnrHIsV0zd9HCYbE/JElshuW6YUI6N3qdGBuYKVWeg3IRFjc
|
||||
# 5vlIFJ7lv94AvXexmBRyFCTfxxEsHwA/w0sUxmcczB4Go5BfXFSLPuMzW4IPxbeG
|
||||
# Ak5xn+lmRT92MYICWjCCAlYCAQEwgYswdzELMAkGA1UEBhMCVVMxHTAbBgNVBAoT
|
||||
# FFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBO
|
||||
# ZXR3b3JrMSgwJgYDVQQDEx9TeW1hbnRlYyBTSEEyNTYgVGltZVN0YW1waW5nIENB
|
||||
# AhB71OWvuswHP6EBIwQiQU0SMAsGCWCGSAFlAwQCAaCBpDAaBgkqhkiG9w0BCQMx
|
||||
# DQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIxMDgxOTIwNDYwM1owLwYJ
|
||||
# KoZIhvcNAQkEMSIEIM6OPKYAsKxVoMXRBP9F7Zl2wKON8btgHT8BfgSoGJtIMDcG
|
||||
# CyqGSIb3DQEJEAIvMSgwJjAkMCIEIMR0znYAfQI5Tg2l5N58FMaA+eKCATz+9lPv
|
||||
# Xbcf32H4MAsGCSqGSIb3DQEBAQSCAQAyIzqp5DBVgMV4D/NogwqQg3FwjOhbiGTi
|
||||
# zhJtcwdNkoazqxTi/Ys8h8uvpJO9T3VH6ifiCsk+i/NA4HkHQ6PYCYdJ6rKOge/W
|
||||
# ACVNwKRdNz0W5+4yYR+W/UM6ufZ/IkLH68pm3Ld5fHK+1GkAc7POEKYIy8aIf34B
|
||||
# c5vNRL1jBKzMKX4j9B2x6RwnALcXWObN3heM4NauNqXlwEd3Hc+5DKU4bLSuQr3L
|
||||
# bmV7CMK2jb0kvF0WlZe8KtVrpW8OFk9h0Lt8I+6MJ7cNg/U1eJ+Mxb8Qv1oAtNr2
|
||||
# oOL6LLl3fzSmtroxt3gDrtUnj+BlPtQnNVg9+w7y1pohad9oiE/5
|
||||
# SIG # End signature block
|
||||
|
67
README.md
67
README.md
@@ -58,17 +58,70 @@ for all the architectures available for that specific combination of version + l
|
||||
Requirements
|
||||
------------
|
||||
|
||||
PowerShell 3.0 or later is required. However the script will detect if you are using an older version and point you to
|
||||
PowerShell 3.0 or later is required. However the script should detect if you are using an older version and point you to
|
||||
the relevant PowerShell 3.0 download page if needed (which should only ever occur if you are running a vanilla version
|
||||
of Windows 7).
|
||||
|
||||
Also, because Internet Explorer is being invoked behind the scenes, if you haven't gone through the first time setup for
|
||||
Internet Explorer, you may receive an error about this when running the script. If that is the case, then you should
|
||||
make sure that you manually launch IE at least once and complete the setup.
|
||||
Note that the current version of the script does not need Internet Explorer to be installed and should also work with
|
||||
PowerShell 7.
|
||||
|
||||
Note however that, if you are running the script elevated, you can work around the above annoyance by using the
|
||||
`-DisableFirstRunCustomize` option which basically __temporarily__ creates a key of the same name in the registry __if__
|
||||
it doesn't already exist, to bypass the first time setup error.
|
||||
Commandline mode
|
||||
----------------
|
||||
|
||||
Fido supports commandline mode whereas, whenever one of the following options is provided, a GUI is not instantiated
|
||||
and you can instead generate the ISO download from within a PowerShell console or script.
|
||||
|
||||
The options are:
|
||||
- `Win`: Specify Windows version (e.g. _"Windows 10"_). Abbreviated version should work as well (e.g `-Win 10`) as long
|
||||
as it is unique enough. If this option isn't specified, the most recent version of Windows is automatically selected.
|
||||
You can obtain a list of supported versions by specifying `-Win List`.
|
||||
- `Rel`: Specify Windows release (e.g. _"21H1"_). If this option isn't specified, the most recent release for the chosen
|
||||
version of Windows is automatically selected. You can also use `-Rel Latest` to force the most recent to be used.
|
||||
You can obtain a list of supported versions by specifying `-Rel List`.
|
||||
- `Ed`: Specify Windows edition (e.g. _"Pro/Home"_). Abbreviated editions should work as well (e.g `-Ed Pro`) as long
|
||||
as it is unique enough. If this option isn't specified, the most recent version of Windows is automatically selected.
|
||||
You can obtain a list of supported versions by specifying `-Ed List`.
|
||||
- `Lang`: Specify Windows language (e.g. _"Arabic"_). Abbreviated or part of a language (e.g. `-Lang Int` for
|
||||
`English International`) should work as long as it's unique enough. If this option isn't specified, the script attempts
|
||||
to select the same language as the system locale.
|
||||
You can obtain a list of supported languages by specifying `-Lang List`.
|
||||
- `Arch`: Specify Windows architecture (e.g. _"x64"_). If this option isn't specified, the script attempts to use the same
|
||||
architecture as the one from the current system.
|
||||
- `GetUrl`: By default, the script attempts to automatically launch the download. But when using the `-GetUrl` switch,
|
||||
the script only displays the download URL, which can then be piped into another command or into a file.
|
||||
|
||||
Examples of a commandline download:
|
||||
|
||||
```
|
||||
PS C:\Projects\Fido> .\Fido.ps1 -Win 10
|
||||
No release specified (-Rel). Defaulting to '21H1 (Build 19043.985 - 2021.05)'.
|
||||
No edition specified (-Ed). Defaulting to 'Windows 10 Home/Pro'.
|
||||
No language specified (-Lang). Defaulting to 'English International'.
|
||||
No architecture specified (-Arch). Defaulting to 'x64'.
|
||||
Selected: Windows 10 21H1 (Build 19043.985 - 2021.05), Home/Pro, English International, x64
|
||||
Downloading 'Win10_21H1_EnglishInternational_x64.iso' (5.0 GB)...
|
||||
PS C:\Projects\Fido> .\Fido.ps1 -Win 10 -Rel List
|
||||
Please select a Windows Release (-Rel) for Windows 10 (or use 'Latest' for most recent):
|
||||
- 21H1 (Build 19043.985 - 2021.05)
|
||||
- 20H2 (Build 19042.631 - 2020.12)
|
||||
- 20H2 (Build 19042.508 - 2020.10)
|
||||
- 20H1 (Build 19041.264 - 2020.05)
|
||||
- 19H2 (Build 18363.418 - 2019.11)
|
||||
- 19H1 (Build 18362.356 - 2019.09)
|
||||
- 19H1 (Build 18362.30 - 2019.05)
|
||||
- 1809 R2 (Build 17763.107 - 2018.10)
|
||||
- 1809 R1 (Build 17763.1 - 2018.09)
|
||||
- 1803 (Build 17134.1 - 2018.04)
|
||||
- 1709 (Build 16299.15 - 2017.09)
|
||||
- 1703 [Redstone 2] (Build 15063.0 - 2017.03)
|
||||
- 1607 [Redstone 1] (Build 14393.0 - 2016.07)
|
||||
- 1511 R3 [Threshold 2] (Build 10586.164 - 2016.04)
|
||||
- 1511 R2 [Threshold 2] (Build 10586.104 - 2016.02)
|
||||
- 1511 R1 [Threshold 2] (Build 10586.0 - 2015.11)
|
||||
- 1507 [Threshold 1] (Build 10240.16384 - 2015.07)
|
||||
PS C:\Projects\Fido> .\Fido.ps1 -Win 10 -Rel 20H2 -Ed Edu -Lang Fre -Arch x86 -GetUrl
|
||||
https://software-download.microsoft.com/db/Win10_Edu_20H2_v2_French_x32.iso?t=c48b32d3-4cf3-46f3-a8ad-6dd9568ff4eb&e=1629113408&h=659cdd60399584c5dc1d267957924fbd
|
||||
```
|
||||
|
||||
Additional Notes
|
||||
----------------
|
||||
|
2
sign.sh
2
sign.sh
@@ -20,6 +20,8 @@ sign_file() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Update the Authenticode signature
|
||||
cmd.exe /c '"C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool" sign /v /sha1 9ce9a71ccab3b38a74781b975f1c228222cf7d3b /fd SHA256 /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp Fido.ps1'
|
||||
read -s -p "Enter pass phrase for `realpath $PRIVATE_KEY`: " PASSWORD
|
||||
echo
|
||||
# Confirm that the pass phrase is valid by trying to sign a dummy file
|
||||
|
Reference in New Issue
Block a user