如何从 powershell 打开已安装的 Microsoft Store 应用程序?

Ale*_*man 5 windows powershell appx

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

Get-AppxPackage -AllUsers
Run Code Online (Sandbox Code Playgroud)

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

powershell -Command "Start-Process 'C:\Program Files\WindowsApps\Microsoft.Windows.Photos_2021.21070.22007.0_x64__8wekyb3d8bbwe\Microsoft.Photos.exe' -Verb runAs"
Run Code Online (Sandbox Code Playgroud)

我收到访问错误:

This command cannot be run due to the error: Access is denied.
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 7

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

注意:不幸的是,Start-Process -Wait(和-PassThru)至少不能与某些 Microsoft Store 应用程序一起使用;该问题已在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...}
Run Code Online (Sandbox Code Playgroud)

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


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

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

Start-Process shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
Run Code Online (Sandbox Code Playgroud)

查找应用程序的 AppID

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

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

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

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

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

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

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

  • 正如您自己所发现的,后缀是包内部应用程序 ID,它在应用程序的清单文件 中定义,该文件appxmanifest.xml位于 下的应用程序特定子文件夹中 $env:Programfiles\WindowsApps;请注意,清单可以包含多个应用程序 ID,Microsoft Photos 的情况确实如此:

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

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

使用 Microsoft Photos 演示该技术:

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

请注意,由于可执行文件是间接启动的因此在返回时不能保证实际的目标进程(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()
Run Code Online (Sandbox Code Playgroud)

完全稳健的方法需要做更多的工作。


将参数传递给 Microsoft Store 应用程序:

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

    # Starts Microsoft Edge and opens the specified URLs.
    # Note: Curiously, this does NOT work with the simpler "MSEdge" AppID.
    Start-Process `
       shell:AppsFolder\Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge `
       -Args 'http://example.org https://wikipedia.org'
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用特定于应用程序的 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'
      
      Run Code Online (Sandbox Code Playgroud)