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)
# 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-AppXPackage
cmdlet的帮助程序函数;例如:
# 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 协议方案和虚拟AppsFolder
shell 文件夹来启动它;例如,启动计算器:
Start-Process shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
Run Code Online (Sandbox Code Playgroud)
查找应用程序的 AppID:
在Windows 10 及更高版本中,您现在可以使用Get-StartApps
cmdlet 列出所有已安装的 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)