如何从 powershell 打开已安装的 Microsoft Store 应用程序?
How to open installed Microsoft Store apps from powershell?
我正在使用此命令获取已安装的 Microsoft Store 应用列表:
Get-AppxPackage -AllUsers
然后我尝试打开一个应用程序:
powershell -Command "Start-Process 'C:\Program Files\WindowsApps\Microsoft.Windows.Photos_2021.21070.22007.0_x64__8wekyb3d8bbwe\Microsoft.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 Store 应用程序一起使用;该问题已在 GitHub issue #10996.
中报告
使用 URI 协议方案 例如 ms-photos:
是最简单的方法,尽管发现给定 Microsoft Store 的应用程序的协议并非易事 - 请参阅 ,它提供了一个辅助函数,Get-AppXUriProtocol
,它建立在标准
的基础上
Get-AppXPackage
命令;例如:
# 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:
,它确实有效。
启动 不 的 Microsoft Store 应用程序定义了 URI 协议方案:
如果给定的应用程序没有定义 URI 协议方案,您必须 - 有点晦涩 - 通过它的 包家族名称 和通用 [ 启动它=24=] URI 协议方案和虚拟 AppsFolder
shell 文件夹,后缀 - 通常但不总是 - 带有 !App
;两个值得注意的例外:
Spotify 需要 !Spotify
(正如您自己发现的那样)。
旧版本的 Microsoft Edge过去需要!MicrosoftEdge
(但是请注意,Edge确实有用于启动的 URI 协议,microsoft-edge:
)。
正如您自己发现的,后缀就是所谓的应用程序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
公平地假设必须使用 first 条目以交互方式启动应用程序,尽管我不清楚是否有官方规则。
使用 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"
请注意,由于可执行文件随后 间接启动 ,实际目标进程(在本例中为 Microsoft.Photos
)在 [=17] 时还不能保证存在=] returns,所以需要做更多的工作,首先等待它存在,然后等待它退出。
在最简单但不完全健壮的情况下,插入一个 Start-Sleep
命令,只要您希望创建目标进程最多需要 [=125] 就可以休眠=](实际时间随系统负载变化):
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 Store 应用程序:
使用 一般 "shell:AppsFolder$packageFamilyName!App"
方法 ,您似乎可以像往常一样通过 Start-Process
' -ArgumentList
传递参数(-Args
) 参数;例如,使用 Microsoft Edge(运行 来自 Windows PowerShell - 如果您有旧版 Edge,请将 !App
替换为 `!MicrosoftEdge:
# Starts Microsoft Edge and opens the specified URLs.
Start-Process ('shell:AppsFolder\' + (Get-AppXPackage *Edge*)[-1].PackageFamilyName + '!App') `
-ArgumentList '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'
我正在使用此命令获取已安装的 Microsoft Store 应用列表:
Get-AppxPackage -AllUsers
然后我尝试打开一个应用程序:
powershell -Command "Start-Process 'C:\Program Files\WindowsApps\Microsoft.Windows.Photos_2021.21070.22007.0_x64__8wekyb3d8bbwe\Microsoft.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 Store 应用程序一起使用;该问题已在 GitHub issue #10996.
使用 URI 协议方案 例如 ms-photos:
是最简单的方法,尽管发现给定 Microsoft Store 的应用程序的协议并非易事 - 请参阅 Get-AppXUriProtocol
,它建立在标准
的基础上
Get-AppXPackage
命令;例如:
# 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:
,它确实有效。
启动 不 的 Microsoft Store 应用程序定义了 URI 协议方案:
如果给定的应用程序没有定义 URI 协议方案,您必须 - 有点晦涩 - 通过它的 包家族名称 和通用 [ 启动它=24=] URI 协议方案和虚拟 AppsFolder
shell 文件夹,后缀 - 通常但不总是 - 带有 !App
;两个值得注意的例外:
Spotify 需要
!Spotify
(正如您自己发现的那样)。旧版本的 Microsoft Edge过去需要
!MicrosoftEdge
(但是请注意,Edge确实有用于启动的 URI 协议,microsoft-edge:
)。正如您自己发现的,后缀就是所谓的应用程序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
公平地假设必须使用 first 条目以交互方式启动应用程序,尽管我不清楚是否有官方规则。
使用 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"
请注意,由于可执行文件随后 间接启动 ,实际目标进程(在本例中为 Microsoft.Photos
)在 [=17] 时还不能保证存在=] returns,所以需要做更多的工作,首先等待它存在,然后等待它退出。
在最简单但不完全健壮的情况下,插入一个 Start-Sleep
命令,只要您希望创建目标进程最多需要 [=125] 就可以休眠=](实际时间随系统负载变化):
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 Store 应用程序:
使用 一般
"shell:AppsFolder$packageFamilyName!App"
方法 ,您似乎可以像往常一样通过Start-Process
'-ArgumentList
传递参数(-Args
) 参数;例如,使用 Microsoft Edge(运行 来自 Windows PowerShell - 如果您有旧版 Edge,请将!App
替换为 `!MicrosoftEdge:# Starts Microsoft Edge and opens the specified URLs. Start-Process ('shell:AppsFolder\' + (Get-AppXPackage *Edge*)[-1].PackageFamilyName + '!App') ` -ArgumentList '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'