使用 powershell 启动 Metro 风格应用程序

Launch Metro style apps using powershell

我正在尝试为 windows 10 编写一个 powershell 脚本,它将自动启动一个 Metro 风格的应用程序。 Start-Process cmdlet 似乎应该可以工作,但我无法让它启动任何东西,除非我提供 .exe

的路径

例如,以下输入有效:

    Start-Process 'C:\Program Files\Internet Explorer\iexplore.exe'

遗憾的是,Metro 风格的应用程序没有可执行文件。我需要使用什么文件来启动它们? 例如,如果我想启动 Windows 商店,我该怎么做?

谢谢

如果 appx 已注册 URI 协议方案,您可以使用该方案启动它。例如,要在 Win8/Win10 中启动 windows 商店,请使用以下代码:

    Start-Process ms-windows-store:

令我惊讶的是,有关启动 Metro 风格应用程序的文档如此之少。

商店应用程序只能由 shell 启动。试试这个:

explorer.exe shell:AppsFolder\Microsoft.WindowsAlarms_8wekyb3d8bbwe!App

我不知道执行此操作的真正通用方法,但您可能可以通过一些中间检查来解决。

注意:我讨厌使用 PowerShell,所以请原谅从 CMD

调用 PS 东西的怪异之处

第 1 步:找出您拥有的应用程序。

powershell Get-AppXPackage 将生成所有这些的列表。假设您特别想要启动 Desktop App Converter,以便您可以在利用自动化的同时处理一些 Centennial 补丁。因此,我将针对 AppX 列表查询可能匹配的内容,使用 findstr 过滤返回的内容。

第 2 步:确定您是否已经拥有所需的应用程序

powershell Get-AppXPackage | findstr /i Desktop

虽然这给了我很多结果,但我可以清楚地看到返回的一组匹配项:

Name              : Microsoft.DesktopAppConverter
PackageFullName   : Microsoft.DesktopAppConverter_2.1.1.0_x64__8wekyb3d8bbwe
InstallLocation   : C:\Program Files\WindowsApps\Microsoft.DesktopAppConverter_2.1.1.0_x64__8wekyb3d8bbwe
PackageFamilyName : Microsoft.DesktopAppConverter_8wekyb3d8bbwe

如果我没有得到这样的东西,下一步自然是得到该死的东西 :) 所以对于下一步,这可能会变得棘手,你的里程可能会有所不同:

第 3 步:找到您可以实际调用应用程序的位置: 我为什么要这样做?因为如果我尝试从 AppXPackage 查询返回的路径 运行 它,我会得到 "Access is denied."

where DesktopAppConverter

C:\Users\user name\AppData\Local\Microsoft\WindowsApps\DesktopAppConverter.exe 

然后您应该能够采用生成的路径并能够从那里运行它。

您可以通过导航到注册表中的此处找到要与 Start-Process 一起使用的命令:Computer\HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol\PackageId

然后展开 ActivatableClassId,然后是应用程序,然后在 CustomProperties 文件夹中查看 Name 的值。

Start-Process 必须 运行 使用 PowerShell,因为在 CMD 中无法识别。

我用它来启动 Windows 邮件应用程序。

如果您下载 Windows SDK,其中有一个名为: microsoft.windows.softwarelogo.appxlauncher.exe 可用于启动 UWP 应用程序。

格式为: microsoft.windows.softwarelogo.appxlauncher.exe <packageFamilyName>!App

您可以通过查看kayleeFrye_OnDeck的回答来获取您的应用程序的packageFamilyName。

它断言 Metro 风格 "App Store" 应用程序没有传统的可执行文件,所以我开始挖掘一点,他们有。从一个旧的 skool 管理 cmd.exe 尝试:

 dir "%ProgramW6432%\WindowsApps"
 dir "%ProgramW6432%\WindowsApps\Microsoft.WindowsCalculator_10.1903.21.0_x64__8wekyb3d8bbwe"      Directory of C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.1903.21.0_x64__8wekyb3d8bbwe

 04/30/2019  05:58 PM    <DIR>          .
 04/30/2019  05:58 PM    <DIR>          ..
 04/30/2019  05:58 PM            35,314 AppxBlockMap.xml
 04/30/2019  05:58 PM             3,860 AppxManifest.xml
 04/30/2019  05:58 PM    <DIR>          AppxMetadata
 04/30/2019  05:58 PM            11,296 AppxSignature.p7x
 04/30/2019  05:58 PM    <DIR>          Assets
 04/30/2019  05:58 PM         4,188,672 Calculator.exe
 04/30/2019  05:58 PM            95,744 CalculatorApp.winmd
 04/30/2019  05:58 PM           286,920 resources.pri
 04/30/2019  05:58 PM    <DIR>          WinMetadata

帮助我找到 Ubuntu、"%ProgramW6432%\WindowsApps\CanonicalGroupLimited.Ubuntu18.04onWindows_1804.2019.522.0_x64__79rhkp1fndgsc\ubuntu1804.exe"

的 exe

因为 WindowsTerminal 而出现在这里的任何人,我为我的个人资料编写了这个功能,这样我就可以在不将手从键盘上移开的情况下提升:

function term {
    $pkgName = (Get-AppxPackage -Name Microsoft.WindowsTerminal).PackageFamilyName
    $Proc = @{
        FilePath = 'explorer.exe'
        ArgumentList = "shell:AppsFolder$pkgName!App"
        Verb = 'RunAs'
    }
    Start-Process @proc
}

现有答案中有有用的信息,但让我尝试将所有内容与自动化步骤结合起来。
此答案假定存在特定于应用程序的 URI 协议如果给定的应用程序不是这样,请通过 shell: URI 方案调用它,如 所示(将这样的 URI 直接传递给 Start-Process 就足够了;例如,
Start-Process shell:AppsFolder\Microsoft.WindowsAlarms_8wekyb3d8bbwe!App)。请注意,您需要知道应用程序系列名称,其中包括抽象发布者 ID (8wekyb3d8bbwe);
Get-AppXPackage 可以帮助发现 - 见下文。

Windows 8+ Metro 风格应用(过时术语)a.k.a UWP 应用程序/AppX 包/Microsoft Store 应用程序 最好由 URLs 使用 特定于应用程序的协议方案 [=95= 启动]:

例如,计算器 Windows 10 应用程序定义了两个 URL 协议名称,calculatorms-calculator,它们都可以与尾随 :Start-Process:

# Note the trailing ":"
Start-Process calculator: # Or: Start-Process ms-calculator:

Microsoft Edge 支持 microsoft-edge 等协议,因此您可以打开给定的 URL,在 Edge 中说 http://example.org 如下:

Start-Process microsoft-edge:http://example.org

请注意,在这种情况下,协议名称后的 : 后跟一个 参数 是如何传递给目标应用程序的。

警告:从 PowerShell (Core) 7.2 开始,许多 AppX 应用程序无法使用 -Wait-PassThru 参数启动 - 请参阅 this GitHub issue.

挑战是如何通过其应用程序名称(程序包名称)发现给定应用程序的协议名称

下一节讨论了可以在注册表中找到此信息的位置,并定义了辅助函数 GetAppXUriProtocol,它可以自动进行此发现,允许您通过 通配符表达式 [=100] 定位应用程序=],如果不知道确切的包名称(这是典型的)。

例如,您可以找到计算器应用程序的协议名称,如下所示:

# Find the protocol names supported by the Calculator application,
# by wildcard expression rather than full package name.
PS> Get-AppXUriProtocol *calculator*

PackageFullName                                            Protocols
---------------                                            ---------
Microsoft.WindowsCalculator_10.1908.0.0_x64__8wekyb3d8bbwe {calculator, ms-calculator}

也就是说,您可以使用 Start-Process calculator:Start-Process ms-calculator: 来启动计算器应用程序。

如果您只需要有关 AppX 包的信息 - 包括协议名称 - 使用标准 Get-AppXPackage cmdlet;例如:

PS> Get-AppXPackage *calculator*
Name              : Microsoft.WindowsCalculator
Publisher         : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
...

发现 AppX 应用程序的 URL 协议名称:

HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol\PackageId 注册表位置具有以已安装的 AppX 包命名的子项,这些子项在 ActivatableClassId\*\CustomProperties 子项的 Name 值中指定了它们支持的 URL 协议名称。

以下函数 Get-AppXUriProtocol 通过 Get-AppXPackage cmdlet 和注册表查找检索与给定 AppX 应用程序关联的协议名称。

该功能支持通配符表达式,因此您可以按包名称的一部分进行搜索,例如应用程序的常用名称;例如
Get-AppXUriProtocol *calc*

Get-AppXUriProtocol源代码:

function Get-AppXUriProtocol {
<#
.SYNOPSIS
Gets the URI protocol names assocated with AppX packages on Windows 8 and above.

.DESCRIPTION
Given AppX package names or wildcard expressions, retrieves all associated
URI protocol names that can be used to launch these applications.

AppX is the package format for UWP applications typically distributed via
the Microsoft Store.

For instance, the protocol names associated with the Windows 10 Calculator
application are 'calculator' and 'ms-calculator', so you can use
Start-Process calculator: (note the appended ":") to launch it.

.PARAMETER PackageName
One or more package family names, full package names, or wildcard expresssions
matching either. 

.EXAMPLE
Get-AppXUriProtocol *calculator*

Outputs a [pscustomobject] instance such as the following:

PackageFullName                                            Protocols
---------------                                            ---------
Microsoft.WindowsCalculator_10.1908.0.0_x64__8wekyb3d8bbwe {calculator, ms-calculator}

#>
  [CmdletBinding(PositionalBinding = $false)]
  [OutputType([pscustomobject])]
  param (
    [Parameter(Mandatory, Position = 0)]
    [SupportsWildcards()]
    [string[]] $PackageName
  )
    
  begin {
    if ($env:OS -ne 'Windows_NT') { Throw "This command is supported on Windows only." }
  }

  process {
    # !! Even though Get-AppXPackage allegedly accepts -Name values from the pipeline
    # !! that doesn't work in practice.
    $packages = foreach ($name in $PackageName) { Get-AppXPackage -Name $name }
    foreach ($package in $packages) {
      $protocolSchemes = (Get-ChildItem registry::HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol\PackageId$($package.PackageFullName)\ActivatableClassId\*\CustomProperties).ForEach('GetValue', 'Name')
      [pscustomobject] @{ 
        PackageFullName = $package.PackageFullName
        Protocols       = $protocolSchemes
      }
    }
  }

}