如何从Powershell打开已安装的Microsoft应用商店应用程序?



我正在使用以下命令获取已安装Microsoft应用商店应用程序的列表:

Get-AppxPackage -AllUsers

然后我尝试打开一个应用程序:

powershell -Command "Start-Process 'C:Program FilesWindowsAppsMicrosoft.Windows.Photos_2021.21070.22007.0_x64__8wekyb3d8bbweMicrosoft.Photos.exe' -Verb runAs"

我收到访问错误:

This command cannot be run due to the error: Access is denied.
# Use the URI scheme of the Microsoft.Photos application.
# Note: Unfortunately, -Wait does *not* work in this case.
Start-Process ms-photos:
# Wait for the process to exit (from what I can tell there's only ever 1
# Microsoft.Photos process).
# The relevant process name was obtained with: Get-Process *Photos*
(Get-Process Microsoft.Photos).WaitForExit()

注意:不幸的是,Start-Process-Wait(和-PassThru)不能与至少某些Microsoft应用商店应用程序一起使用;GitHub 问题 #10996 中报告了此问题。

使用URI 协议方案(如ms-photos:)是最简单的方法,尽管发现给定的 Microsoft Store 应用程序的协议并非易事 - 请参阅此答案,它提供了一个帮助程序函数Get-AppXUriProtocol,它基于标准
Get-AppXPackagecmdlet 构建;例如:

# Note: 
#  * Requires custom function Get-AppXUriProtocol from the linked answer.
#  * Must be run in *Windows PowerShell*, because the AppX module
#    isn't supported in PowerShell (Core), as of v7.1.
PS> Get-AppXUriProtocol *Photos* | Format-List
PackageFullName : Microsoft.Windows.Photos_2021.21070.22007.0_x64__8wekyb3d8bbwe
Protocols       : {ms-wcrv, ms-wpdrmv, ms-photos, microsoft.windows.photos.crop...}

如您所见,Microsoft Photos应用程序具有多个与之关联的协议方案,但是简单地启动该应用程序的明显候选者是ms-photos:,这确实有效。


启动定义 URI 协议方案的Microsoft存储应用程序:

如果给定的应用程序没有定义 URI 协议方案,则必须 - 有点模糊地 - 通过其AppId(应用程序 ID)以及通用shell:URI 协议方案和虚拟AppsFoldershell 文件夹启动它;例如,要启动计算器:

Start-Process shell:AppsFolderMicrosoft.WindowsCalculator_8wekyb3d8bbwe!App

查找应用程序的 AppID

  • Windows 10 及更高版本中,你现在可以使用Get-StartAppscmdlet 列出所有已安装的 AppX 应用程序,或按其显示名称(部分)进行搜索,该名称报告其 AppID。因此,如果您知道应用程序的完整显示名称,例如Photos,您可以按如下方式启动它:

    Start-Process "shell:AppsFolder$((Get-StartApps Photos | Select-Object -First 1).AppId)"
    
    • 注意:Select-Object -First 1的原因是,即使指定确切的显示名称也可能导致多个结果,例如Microsoft Edge

    • 如果您不确定完整的显示名称,则可以使用子字符串来查找匹配的应用程序;例如Get-StartApps edge

  • 在旧版本中,您必须手动确定AppID,不幸的是,这非常麻烦:请继续阅读。

AppID 由系列包名称组成(例如Microsoft.MicrosoftEdge_8wekyb3d8bbwe) 后跟!和包内部标识符,通常 - 但并不总是!App;两个值得注意的例外

  • Spotify需要!Spotify(正如你自己发现的那样)。

  • MicrosoftEdge 使用!MicrosoftEdge(但请注意,Edge 确实有一个用于 URI 协议,用于 lauching、microsoft-edge:,还有一个更简单的 AppID,MSEdge,尽管它不支持传递参数(见下文))。

  • 正如您自己所发现的,后缀是包内部应用程序 ID,它在应用程序的清单文件中定义,appxmanifest.xml,位于$env:ProgramfilesWindowsApps下特定于应用程序的子文件夹中;请注意,清单可以包含多个应用程序 ID,就像 Microsoft 照片一样:

    # Run in *Windows PowerShell*.
    # For Microsoft Photos, the following application IDs are reported:
    #   'App', 'SecondaryEntry'
    $appManifestPath = (Get-AppxPackage *Photos*)[-1].InstallLocation + 'appxmanifest.xml'
    (
    Select-Xml '//ns:Application' $appManifestPath `
    -Namespace @{ ns='http://schemas.microsoft.com/appx/manifest/foundation/windows10' }
    ).Node.Id                                                                                                 
    

假设以交互方式启动应用程序必须使用第一个条目是公平的,尽管我不清楚是否有官方规则。

要使用"Microsoft照片"演示该技术,请执行以下操作:

# Get the package family name (the assumption here is that only *1* package matches).
# Note: While you must run the Get-AppXPackage from *Windows PowerShell*
#       you can use the resulting package name to launch the application
#       from PowerShell (Core) too.
$packageFamilyName = (Get-AppXPackage *Photos*).PackageFamilyName
Start-Process "shell:AppsFolder$packageFamilyName!App"

请注意,由于可执行文件随后是间接启动的,因此实际的目标进程(在本例中为Microsoft.Photos)在Start-Process返回时还不能保证存在,因此需要做更多的工作来首先等待它的存在,然后等待它退出。

在最简单但不是完全健壮的情况下,插入一个Start-Sleep命令,只要您期望创建目标进程最多需要多长时间(实际时间因系统负载而异):

Start-Process "shell:AppsFolder$packageFamilyName!App"
Start-Sleep -Seconds 5 # Wait for the Microsoft.Photos process to be created.
(Get-Process Microsoft.Photos).WaitForExit()

一个完全健全的方法需要更多的工作。


参数传递给Microsoft应用商店应用程序:

  • 使用一般的"shell:AppsFolder$appId"方法,您似乎可以像往常一样通过Start-Process'-ArgumentList(-Args) 参数传递参数;例如,使用 Microsoft Edge(从Windows PowerShell运行 - 如果您有较旧的 Edge 版本,请将!App替换为 '!微软边缘:

    # Starts Microsoft Edge and opens the specified URLs.
    # Note: Curiously, this does NOT work with the simpler "MSEdge" AppID.
    Start-Process `
    shell:AppsFolderMicrosoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge `
    -Args 'http://example.org https://wikipedia.org'
    
  • 使用特定于应用的 URI 方案方法,参数必须作为 URI 的一部分传递(-ArgumentList将被忽略):

    • 警告我不清楚如何传递多个参数,以及通常,是否有跨应用程序的标准化方法在 URI 中嵌入参数。

    • 例如,Microsoft Edge 似乎只接受一个参数:要打开的网站的 URL。该 URL 之后的任何内容似乎都被解释为该 URL 的一部分:

      # Starts Microsoft Edge an opens the specified URL.
      Start-Process 'microsoft-edge:https://en.wikipedia.org?search=wikipedia'
      

最新更新