如何使用 Powershell 从 Windows 应用商店安装应用程序

Dav*_*son 8 automation windows powershell

我知道如果我有 .appx 包文件,我可以使用Add-AppxPackagecmdlet通过 powershell 安装它。但是,我只想按名称下载和安装 Microsoft Store 软件包。

我不想去 Microsoft Store 页面,启动 fiddler,开始下载,捕获 .appx 文件 URL,然后手动下载它以便我可以使用Add-AppxPackage. (在此处查看 Windows 操作系统中心是如何做到的)

这可能很有趣 - 但它会很脆弱。我需要一个强大的可编写脚本的方法来管理 Windows 应用商店应用程序。

(有一些软件包只能通过 Microsoft Store 访问。我可以通过 Chocolatey 或直接下载 msi 获得其他所有内容。)

一个实例中,我还不能脚本是安装的HEIF图像扩展(以查看来自iPhone图像格式需要:*.HEIC格式。

一旦我从 Windows 应用商店安装它,它就会显示 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
Run Code Online (Sandbox Code Playgroud)

我想要的是 cmdlet:Download-AppxPackage以便我可以执行以下操作:

Download-AppxPackage -Name "Microsoft.HEVCVideoExtension"
Run Code Online (Sandbox Code Playgroud)

有谁知道我怎么能做到这一点?

小智 13

您现在可以使用winget在 Windows 10 和 11 上安装 msstore 应用程序。用于winget search <app_name> --source=msstore进行搜索,并使用应用程序的 id 来安装和升级应用程序。例如,要安装 Netflix:

  1. 首先我进行了搜索winget search Netflix --source=msstore,我看到应用程序 ID 是9WZDNCRFJ3TJ
  2. 我安装应用程序与winget install -e -i --id=9WZDNCRFJ3TJ --source=msstore.
  3. 我用 升级应用程序winget upgrade -e -i --id=9WZDNCRFJ3TJ


小智 6

进一步构建 AJ 的答案。使用 powershell 从 Windows 应用商店下载任何应用程序,只需提供商店的 url 和保存路径。

用法:

Download-AppxPackage "https://www.microsoft.com/p/dynamic-theme/9nblggh1zbkw" "$ENV:USERPROFILE\Desktop"
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

代码:

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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这可以正确下载中性和 x64 软件包,但未经针对 arm 和 32 位系统的测试。该路径必须指向一个文件夹。它将下载包及其依赖项,并将它们全部保存为其原始文件名,同时避免像 chrome 那样的名称冲突。


BCI*_*BCI 6

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"
Run Code Online (Sandbox Code Playgroud)

修改了脚本,使其删除旧版本并仅下载最新版本。

非常感谢 Yorai Levi 的原创剧本!


小智 5

store.rg-adguard.net是一个 GUI,用于生成商店应用程序的直接下载链接。查看该页面的源代码,我们可以搭载它们直接下载内容,但使用PackageFamilyName,而不是Name(在您的示例中,它将是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"   
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这仅限于 x64 版本,并且路径必须指向文件夹。它将下载包及其依赖项并将它们全部保存为PackagefamilyName ( n ).appx