问题描述
我将 Win32 控制台应用程序打包到 MSIX 包中。在 Win 10 上一切正常。我也可以在 Windows Server 2019 上安装它,但无法通过调用别名或任何其他方式从控制台在那里运行它。
- 应用安装在C:\Program Files\WindowsApps\stackmuncher_1.1.1.0_x64__eqf80b1s88fx6
- 在 C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps 中有一个它的别名作为零长度文件
- 如果我将可执行文件从 C:\Program Files\WindowsApps\stackmuncher_1.1.1.0_x64__eqf80b1s88fx6 复制到任何其他文件夹,我就可以运行该应用程序
- 别名显示在设置 > 应用执行别名
如果我尝试通过 PS 或 CMD 终端的别名 stackmuncher.exe
运行应用程序,我会收到“未找到”消息。
我将 %userprofile%\AppData\Local\Microsoft\WindowsApps
添加到系统 Path
变量并得到不同的错误:
程序“stackmuncher.exe”无法运行:指定的可执行文件不是适用于此操作系统平台的有效应用程序
该应用似乎已安装,并且它正常运行所需的所有文件都在那里。
如何使用别名或其他方式运行它?
包裹信息
PS C:\rust\stm> get-appxpackage | Where-Object { $_.Name -like "*stackmuncher*" }
Name : stackmuncher
Publisher : CN=stackmuncher,C=NZ
Architecture : X64
ResourceId :
Version : 1.1.1.0
PackageFullName : stackmuncher_1.1.1.0_x64__eqf80b1s88fx6
InstallLocation : C:\Program Files\WindowsApps\stackmuncher_1.1.1.0_x64__eqf80b1s88fx6
IsFramework : False
PackageFamilyName : stackmuncher_eqf80b1s88fx6
PublisherId : eqf80b1s88fx6
IsResourcePackage : False
IsBundle : False
IsDevelopmentMode : False
NonRemovable : False
IsPartiallyStaged : False
SignatureKind : Developer
Status : Ok
AppManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
>
<Identity Name="stackmuncher" Version="1.1.1.0" Publisher="CN=stackmuncher,C=NZ" ProcessorArchitecture="x64" />
<Properties>
<displayName>stackmuncher</displayName>
<PublisherdisplayName>stackmuncher</PublisherdisplayName>
<Description>stackmuncher app</Description>
<logo>150.png</logo>
</Properties>
<Resources>
<Resource Language="en-us" />
</Resources>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14316.0" MaxVersionTested="10.0.15063.0" />
</Dependencies>
<Capabilities>
<rescap:Capability Name="runFullTrust"/>
</Capabilities>
<Applications>
<Application Id="stackmuncher" Executable="stackmuncher.exe" EntryPoint="Windows.PartialTrustApplication">
<uap:VisualElements displayName="stackmuncher" Description="stackmuncher app" Square150x150logo="150.png" Square44x44logo="44.png" BackgroundColor="#999999" />
<Extensions>
<uap3:Extension Category="windows.appExecutionAlias" EntryPoint="Windows.FullTrustApplication" Executable="stackmuncher.exe">
<uap3:AppExecutionAlias>
<desktop:ExecutionAlias Alias="stackmuncher.exe"/>
</uap3:AppExecutionAlias>
</uap3:Extension>
</Extensions>
</Application>
</Applications>
</Package>
完整的错误信息
PS C:\> stackmuncher.exe
Program 'stackmuncher.exe' Failed to run: The specified executable is not a valid application for this OS platform.At
line:1 char:1
+ stackmuncher.exe
+ ~~~~~~~~~~~~~~~~.
At line:1 char:1
+ stackmuncher.exe
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [],ApplicationFailedException
+ FullyQualifiedErrorId : NativeCommandFailed
- 安装程序:https://distro.stackmuncher.com/msix/stackmuncher.msix
- 自签名证书:https://distro.stackmuncher.com/stm.cer
解决方法
正如您在评论中提到的,Win Server 2019 不支持执行别名(遗憾的是)。我刚刚在尝试在使用 Windows Server 2019 的 GitHub Actions 上测试我的 MSIX 包时遇到了同样的问题。
我找到了几种运行安装包的方法。
-
使用 PowerShell command
Invoke-CommandInDesktopPackage
。您也可以调用主可执行文件。我测试了这种方法,它有效(虽然在我的机器上),但很难从代码中做到这一点,然后将其附加到目标应用程序进程。 -
另一种方法是使用类似的命令运行应用程序
explorer.exe shell:appsFolder\<ApplicationID>!<AppID>
。这种方法描述了here with handy scripts。我还没有找到添加命令行参数的方法,所以对我来说不太好。 -
使用协议。它需要对应用程序进行额外的更改,但对我来说,这是最简单、最可靠的方法。因此,我按照 in this article 所述为我的应用添加了协议支持。在我的代码中,我只是添加了几行来支持这种类型的参数:
public AppConfigBuilder AppendCommandLineArgs(string[] args) { const string protocol = "myproto:?"; bool isProtocolUsage = args.Any() && args[0].StartsWith(protocol); string[] keyValueArgs = isProtocolUsage ? args[0][(args[0].IndexOf("?",StringComparison.Ordinal) + 1)..].Split('&') : args; var configuration = new ConfigurationBuilder() .AddCommandLine(keyValueArgs) .Build(); ... }
基本上,我将其转换为常规参数并将其传递给 ConfigurationBuilder,后者处理得很好。