updated script v2

This commit is contained in:
Justin Bailey
2023-02-16 17:31:22 -05:00
parent a4d0269af4
commit 4b808cb67d
+100 -34
View File
@@ -1,60 +1,126 @@
Param (
[Parameter(Mandatory = $True)]
[ValidatePattern('^https?://')]
<#
.SYNOPSIS
Downloads any free app and its dependencies from the Microsoft Store.
.DESCRIPTION
This script downloads any free app and its dependencies from the Microsoft Store, given a valid Store URL. The downloaded files are saved to the specified directory.
.PARAMETER StoreURL
The URL of the Microsoft Store page for the app to download.
.PARAMETER SavePathRoot
The root directory where the downloaded files should be saved. The default value is "%tmp%".
.EXAMPLE
pwsh .\msix_downloader.ps1 -StoreURL https://www.microsoft.com/store/productId/9NCB4Z0TZ6RR
Downloads the Microsoft Solitaire Collection app and its dependencies from the Microsoft Store, and saves the files to the default directory.
.NOTES
Author: beholdenkey
Date: 2023-02-16
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0, HelpMessage = "The URL of the Microsoft Store page for the app to download.")]
[ValidateNotNullOrEmpty()]
[string] $StoreURL,
[Parameter(Mandatory = $False)]
[ValidateScript({ Test-Path $_ -PathType Container })]
$SavePathRoot = "$env:TEMP\$($StoreURL.Substring($StoreURL.LastIndexOf('/') + 1))"
[Parameter(Mandatory = $false, Position = 1, HelpMessage = "The root directory where the downloaded files should be saved. The default value is the system temporary directory.")]
[ValidateNotNullOrEmpty()]
[string] $SavePathRoot = [System.IO.Path]::GetTempPath()
)
# Set up error handling
$ErrorActionPreference = "Stop"
$ErrorMessage = ""
try {
$wchttp = [System.Net.WebClient]::new()
# Remove trailing slash from Store URL, if any
if ($StoreURL.EndsWith("/")) {
$StoreURL = $StoreURL.Remove($StoreUrl.Length - 1, 1)
}
# Query the API to get the download links for the app
$wc = [System.Net.WebClient]::new()
$URI = "https://store.rg-adguard.net/api/GetFiles"
$myParameters = "type=url&url=$($StoreURL)"
$wc.Headers[[System.Net.HttpRequestHeader]::ContentType] = "application/x-www-form-urlencoded"
$HtmlResult = $wc.UploadString($URI, $myParameters)
$wchttp.Headers[[System.Net.HttpRequestHeader]::ContentType] = "application/x-www-form-urlencoded"
$HtmlResult = $wchttp.UploadString($URI, $myParameters)
$Start = $HtmlResult.IndexOf("<p>The links were successfully received from the Microsoft Store server.</p>")
if ($Start -eq -1) {
# Parse the HTML response to get the download links
$start = $HtmlResult.IndexOf("<p>The links were successfully received from the Microsoft Store server.</p>")
if ($start -eq -1) {
throw "Could not get the links, please check the StoreURL."
}
$TableEnd = ($HtmlResult.LastIndexOf("</table>") + 8)
$SemiCleaned = $HtmlResult.Substring($start, $TableEnd - $start)
$tableEnd = ($HtmlResult.LastIndexOf("</table>") + 8)
$semiCleaned = $HtmlResult.Substring($start, $tableEnd - $start)
$newHtml = New-Object -ComObject "HTMLFile"
try {
$newHtml.IHTMLDocument2_write($SemiCleaned)
# This works in PowerShell with Office installed
$newHtml.IHTMLDocument2_write($semiCleaned)
}
catch {
$src = [System.Text.Encoding]::Unicode.GetBytes($SemiCleaned)
# This works when Office is not installed
$src = [System.Text.Encoding]::Unicode.GetBytes($semiCleaned)
$newHtml.write($src)
}
$ToDownload = $newHtml.getElementsByTagName("a") | Select-Object textContent, href
$toDownload = $newHtml.getElementsByTagName("a") | Select-Object textContent, href
# Create the directory to save the downloaded files
$SavePathRoot = $([System.Environment]::ExpandEnvironmentVariables("$SavePathRoot"))
$lastFrontSlash = $StoreURL.LastIndexOf("/")
$productID = $StoreURL.Substring($lastFrontSlash + 1, $StoreURL.Length - $lastFrontSlash - 1)
$path = Join-Path $SavePathRoot $productID
if (!(Test-Path $path)) {
New-Item -ItemType Directory $path -ErrorAction Stop | Out-Null
Write-Verbose "Created directory $path."
}
if (!(Test-Path -Path $SavePathRoot)) {
New-Item -ItemType Directory -Path $SavePathRoot -ErrorAction Stop | Out-Null
# Download the files
$totalSize = $toDownload | Measure-Object -Property href -Sum | Select-Object -ExpandProperty Sum
$currentSize = 0
foreach ($download in $toDownload) {
$downloadPath = Join-Path $path $download.textContent
$progressLabel = "Downloading $($download.textContent)..."
$progressPercentage = [math]::Round(($currentSize / $totalSize) * 100, 0)
Write-Progress -Activity "Downloading files" -Status $progressLabel -PercentComplete $progressPercentage
try {
$wc.DownloadFile($download.href, $downloadPath)
Write-Verbose "Downloaded $($download.textContent) to $downloadPath."
}
catch {
$ErrorMessage = "Failed to download $($download.textContent): $_"
Write-Error $ErrorMessage
}
$currentSize += $wc.ResponseHeaders["Content-Length"]
}
Foreach ($Download in $ToDownload) {
Write-Progress -Activity "Downloading $($Download.textContent)..." -Status "Working"
$wchttp.DownloadFile($Download.href, "$SavePathRoot\$($Download.textContent)")
}
Write-Host "---------------------------------------"
Write-Host ""
Write-Host "Download is complete."
Write-Host "Opening Folder"
# Open the directory where the files were saved
Write-Verbose "Download complete. Opening directory $path."
Start-Sleep -Seconds 3
Start "$SavePathRoot"
Start $path
}
catch {
Write-Error $_.Exception.Message
$ErrorMessage = "An error occurred while downloading the app: $_"
Write-Error $ErrorMessage
}
finally {
# Clean up
$wc.Dispose()
}
if ($ErrorMessage -ne "") {
throw $ErrorMessage
}