How do I install an app from Windows Store using Powershell
Solution 1
store.rg-adguard.net is a GUI for generating direct download links to store apps. Peeking at the source of that page, we can piggyback off them to download the content directly, but using PackageFamilyName, rather than Name (in your example it would be Microsoft.HEVCVideoExtension_8wekyb3d8bbwe).
function Download-AppxPackage {
[CmdletBinding()]
param (
[string]$PackageFamilyName,
[string]$Path
)
process {
$WebResponse = Invoke-WebRequest -Method 'POST' -Uri 'https://store.rg-adguard.net/api/GetFiles' -Body "type=PackageFamilyName&url=$PackageFamilyName&ring=Retail" -ContentType 'application/x-www-form-urlencoded'
$LinksMatch = $WebResponse.Links | where {$_ -like '*_x64*.appx*'} | Select-String -Pattern '(?<=a href=").+(?=" r)'
$DownloadLinks = $LinksMatch.matches.value
for ($i = 1; $i -le $DownloadLinks.Count; $i++) {
Invoke-WebRequest -Uri $DownloadLinks[$i-1] -OutFile "$Path\$PackageFamilyName($i).appx"
}
}
}
This is limited to the x64 version, and the path must point to a folder. It will download the package and its dependencies and save them all as PackagefamilyName(n).appx
Solution 2
function Download-AppxPackage {
[CmdletBinding()]
param (
[string]$Uri,
[string]$Path = "."
)
process {
echo ""
$StopWatch = [system.diagnostics.stopwatch]::startnew()
$Path = (Resolve-Path $Path).Path
#Get Urls to download
Write-Host -ForegroundColor Yellow "Processing $Uri"
$WebResponse = Invoke-WebRequest -UseBasicParsing -Method 'POST' -Uri 'https://store.rg-adguard.net/api/GetFiles' -Body "type=url&url=$Uri&ring=Retail" -ContentType 'application/x-www-form-urlencoded'
$LinksMatch = ($WebResponse.Links | where {$_ -like '*.appx*'} | where {$_ -like '*_neutral_*' -or $_ -like "*_"+$env:PROCESSOR_ARCHITECTURE.Replace("AMD","X").Replace("IA","X")+"_*"} | Select-String -Pattern '(?<=a href=").+(?=" r)').matches.value
$Files = ($WebResponse.Links | where {$_ -like '*.appx*'} | where {$_ -like '*_neutral_*' -or $_ -like "*_"+$env:PROCESSOR_ARCHITECTURE.Replace("AMD","X").Replace("IA","X")+"_*"} | where {$_ } | Select-String -Pattern '(?<=noreferrer">).+(?=</a>)').matches.value
#Create array of links and filenames
$DownloadLinks = @()
for($i = 0;$i -lt $LinksMatch.Count; $i++){
$Array += ,@($LinksMatch[$i],$Files[$i])
}
#Sort by filename descending
$Array = $Array | sort-object @{Expression={$_[1]}; Descending=$True}
$LastFile = "temp123"
for($i = 0;$i -lt $LinksMatch.Count; $i++){
$CurrentFile = $Array[$i][1]
$CurrentUrl = $Array[$i][0]
#Find first number index of current and last processed filename
if ($CurrentFile -match "(?<number>\d)"){}
$FileIndex = $CurrentFile.indexof($Matches.number)
if ($LastFile -match "(?<number>\d)"){}
$LastFileIndex = $LastFile.indexof($Matches.number)
#If current filename product not equal to last filename product
if (($CurrentFile.SubString(0,$FileIndex-1)) -ne ($LastFile.SubString(0,$LastFileIndex-1))) {
#If file not already downloaded, add to the download queue
if (-Not (Test-Path "$Path\$CurrentFile")) {
"Downloading $Path\$CurrentFile"
$FilePath = "$Path\$CurrentFile"
$FileRequest = Invoke-WebRequest -Uri $CurrentUrl -UseBasicParsing #-Method Head
[System.IO.File]::WriteAllBytes($FilePath, $FileRequest.content)
}
#Delete file outdated and already exist
}elseif ((Test-Path "$Path\$CurrentFile")) {
Remove-Item "$Path\$CurrentFile"
"Removing $Path\$CurrentFile"
}
$LastFile = $CurrentFile
}
"Time to process: "+$StopWatch.ElapsedMilliseconds
}
}
if (-Not (Test-Path "C:\Support\Store")) {
Write-Host -ForegroundColor Green "Creating directory C:\Support\Store"
New-Item -ItemType Directory -Force -Path "C:\Support\Store"
}
Download-AppxPackage "https://www.microsoft.com/p/snip-sketch/9mz95kl8mr0l" "C:\Support\Store"
Modified the script so that it delete old versions and only download latest.
Much thanks to Yorai Levi for the original script!
Solution 3
Building further on AJ's Answer. Download any app from windows app store with powershell just supply a url from the store and a path for saving.
Usage:
Download-AppxPackage "https://www.microsoft.com/p/dynamic-theme/9nblggh1zbkw" "$ENV:USERPROFILE\Desktop"
C:\Users\user\Desktop\55888ChristopheLavalle.DynamicTheme_1.4.30233.0_neutral_~_jdggxwd41xcr0.AppxBundle
C:\Users\user\Desktop\55888ChristopheLavalle.DynamicTheme_1.4.30234.0_neutral_~_jdggxwd41xcr0.AppxBundle
C:\Users\user\Desktop\Microsoft.NET.Native.Framework.1.7_1.7.27413.0_x64__8wekyb3d8bbwe.Appx
C:\Users\user\Desktop\Microsoft.NET.Native.Runtime.1.7_1.7.27422.0_x64__8wekyb3d8bbwe.Appx
C:\Users\user\Desktop\Microsoft.Services.Store.Engagement_10.0.19011.0_x64__8wekyb3d8bbwe.Appx
C:\Users\user\Desktop\Microsoft.VCLibs.140.00_14.0.29231.0_x64__8wekyb3d8bbwe.App
Code:
function Download-AppxPackage {
[CmdletBinding()]
param (
[string]$Uri,
[string]$Path = "."
)
process {
$Path = (Resolve-Path $Path).Path
#Get Urls to download
$WebResponse = Invoke-WebRequest -UseBasicParsing -Method 'POST' -Uri 'https://store.rg-adguard.net/api/GetFiles' -Body "type=url&url=$Uri&ring=Retail" -ContentType 'application/x-www-form-urlencoded'
$LinksMatch = $WebResponse.Links | where {$_ -like '*.appx*'} | where {$_ -like '*_neutral_*' -or $_ -like "*_"+$env:PROCESSOR_ARCHITECTURE.Replace("AMD","X").Replace("IA","X")+"_*"} | Select-String -Pattern '(?<=a href=").+(?=" r)'
$DownloadLinks = $LinksMatch.matches.value
function Resolve-NameConflict{
#Accepts Path to a FILE and changes it so there are no name conflicts
param(
[string]$Path
)
$newPath = $Path
if(Test-Path $Path){
$i = 0;
$item = (Get-Item $Path)
while(Test-Path $newPath){
$i += 1;
$newPath = Join-Path $item.DirectoryName ($item.BaseName+"($i)"+$item.Extension)
}
}
return $newPath
}
#Download Urls
foreach($url in $DownloadLinks){
$FileRequest = Invoke-WebRequest -Uri $url -UseBasicParsing #-Method Head
$FileName = ($FileRequest.Headers["Content-Disposition"] | Select-String -Pattern '(?<=filename=).+').matches.value
$FilePath = Join-Path $Path $FileName; $FilePath = Resolve-NameConflict($FilePath)
[System.IO.File]::WriteAllBytes($FilePath, $FileRequest.content)
echo $FilePath
}
}
}
This correctly downloads neutral and x64 packages but untested for arm and 32bit systems. the path must point to a folder. It will download the package and its dependencies and save them all as their original file names while avoiding name collisions like chrome.
David Wilson
Updated on September 18, 2022Comments
-
David Wilson over 1 year
I know if I have .appx package file, I can install it via powershell with the
Add-AppxPackage
cmdlet. However, I simply want to download & install Microsoft Store packages by name.I don't want to have to go to the Microsoft Store page, start fiddler, start the download, capture the .appx file URL and then manually download it so that I can use
Add-AppxPackage
. (See how Windows OS Hub did that here)That could be fun - but it will be flaky. I need a robust scriptable method for managing Windows Store apps.
(There are a few software packages that are only accessible via Microsoft Store. Everything else I can get via Chocolatey or direct msi download.)
One example that I can't yet script is installation of the HEIF Image Extensions (needed to view the image format from iPhones:
*.HEIC
format.Once I install this from the Windows Store, it shows up with
Get-AppxPackage
PS C:\Tools> Get-AppxPackage | Where-Object {$_.Name -eq "Microsoft.HEVCVideoExtension" } Name : Microsoft.HEVCVideoExtension Publisher : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US Architecture : X64 ResourceId : Version : 1.0.31053.0 PackageFullName : Microsoft.HEVCVideoExtension_1.0.31053.0_x64__8wekyb3d8bbwe InstallLocation : C:\Program Files\WindowsApps\Microsoft.HEVCVideoExtension_1.0.31053.0_x64__8wekyb3d8bbwe IsFramework : False PackageFamilyName : Microsoft.HEVCVideoExtension_8wekyb3d8bbwe PublisherId : 8wekyb3d8bbwe IsResourcePackage : False IsBundle : False IsDevelopmentMode : False NonRemovable : False Dependencies : {Microsoft.VCLibs.140.00_14.0.27810.0_x64__8wekyb3d8bbwe} IsPartiallyStaged : False SignatureKind : Store Status : Ok
What I want is the cmdlet:
Download-AppxPackage
so that I can do:Download-AppxPackage -Name "Microsoft.HEVCVideoExtension"
Does anyone know how I can do this?
-
Admin almost 4 yearsProbably more suited to superuser.com
-
Admin almost 2 yearsI submitted a feature request on their GitHub.
-
-
David Wilson almost 4 yearsThanks - this is a good improvement. Not ideal as: a) I have to manualy install to find out the PackageFamilyName - and it may change. And: b) I don't know who "rg-adguard.net" are. I'll accept this as answer as probably best we can do until MS give me the cmdlet I want. They may want to divert users to the store to see ads etc.
-
DeerSpotter almost 3 yearsas of: 06/25/2021 this is broken. Download-AppxPackage no longer works
-
DeerSpotter almost 3 yearsas of: 06/25/2021 this is broken. Download-AppxPackage no longer works
-
DeerSpotter almost 3 yearsas of: 06/25/2021 this is broken. Download-AppxPackage no longer works
-
Yorai Levi almost 3 yearshey @DeerSpotter what package did you try to download? my example still runs on my system
-
André almost 3 yearsThanks, it works. I didn't understand though why this fn downloads multiple versions of the same package. E.g. I tried with microsoft.com/pt-br/p/windbg/9pgjgd53tn86 and it downloaded both
Microsoft.WinDbg_1.2104.13002.0_neutral__8wekyb3d8bbwe.Appx
andMicrosoft.WinDbg_1.2103.1004.0_neutral__8wekyb3d8bbwe.Appx
-
Yorai Levi almost 3 years@André this script doesn't attempt to version check it just performs the download, you are welcome to share an adaptation that version checks~ I am sure it will be helpful for everyone
-
Mavaddat Javid over 2 years