65.9K
CodeProject 正在变化。 阅读更多。
Home

将现有应用程序引入 Microsoft Store

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.74/5 (7投票s)

2019 年 7 月 22 日

CPOL

10分钟阅读

viewsIcon

9545

将您现有的 WPF 和 Winform 应用程序引入 Microsoft Store

目录

引言

2016 年年中,微软推出了桌面桥,作为将传统 Win32 应用程序打包并分发到 Microsoft Store 的一种方式。在此模式下运行的 Win32 应用程序可以访问 UWP API。在本文中,我们将探讨如何使用桌面应用转换器和 MSIX 打包工具打包应用程序,并使用应用认证对应用进行认证,所有这些工具都可以在 Microsoft Store 免费下载。桌面应用转换器已于 2018 年末被 MSIX 打包工具取代。前者是命令行工具,后者是 GUI 工具。两者都有各自的优缺点。对于命令行,相同的命令可以直接复制粘贴到命令提示符中,并可以轻松通过构建脚本实现自动化,而使用 GUI,每次都必须在 UI 中重新输入选项和信息。

本文中的所有知识都是在我提交幻灯片应用程序时收集的。该应用程序是一个 WPF 应用程序,其 DirectX 和视频编码后端是用 C++ 编写的。WPF 使用 pinvoke 调用 C++ 代码。我已在以下两篇文章中开源了该应用程序中使用的视频编码器

事不宜迟,让我们开始吧。

预留您的应用名称

如果您认真考虑将应用程序提交到 MS Store,请前往 dev.windows.com 注册一个开发者帐户。您可以选择个人帐户或公司帐户。前者费用为 24 美元,后者为 120 美元。设置费用的原因是为了筛选那些只是玩玩的人与那些真正有强烈意愿完成此项工作的人。您可以最多预留您的应用名称 3 个月。目前尚不清楚,如果到期时应用仍未提交,是否可以再次预留相同的名称。

AppData 路径

UWP 应用程序有自己的 AppData 文件夹,与普通 Win32 应用程序的文件夹不同。建议检测 UWP 模式并以编程方式更改 AppData 路径。下面是我的应用程序 Mandy Frenzy 的普通 Win32 AppData。当 UWP 应用程序被卸载时,其对应的 AppData 文件夹也会被删除。

C:\Users\{username}\AppData\Local\MandyFrenzy

这是 UWP AppData。请注意,无需附加您的应用程序名称,因为该路径已经是您的应用程序路径。

C:\Users\{username}\AppData\Local\Packages\xxxxMandyFrenzy_xxxxxxxx\LocalState

要检测 UWP 模式,请安装 nuget 包:DesktopBridge.Helpers。UWP 检测代码如下。

DesktopBridge.Helpers helper = new DesktopBridge.Helpers();
if (helper.IsRunningAsUwp())
{ // do your UWP specific work here }

要获取 UWP AppData 路径,请添加对 C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd 的库引用。注意:您的实际路径可能与我的不同,具体取决于 Windows SDK 的安装位置和版本。Windows.winmd 不包含代码,只包含有关 UWP 类和 API 的元数据。每次在 Visual Studio 中构建应用程序时,Windows.winmd 都会复制到输出。在使用应用程序打包工具或应用程序认证工具之前,请从输出文件夹中删除 Windows.winmd。以下是访问 AppData 路径的方法。

string appLocalFolder = Windows.Storage.ApplicationData.Current.LocalFolder.Path;

资产

由于您的 UWP 在沙盒中运行,所有相对于可执行文件路径的资源(如图像和着色器)都无法加载,尽管 DLL 可以正常加载。最可靠的方法是嵌入所有资源。您可以使用以下代码以编程方式获取安装路径,并附加您的资源路径以加载资源。这种方法高度不可靠,有时可以,有时您的应用程序会被禁止访问其自己的 Windows 包文件夹,特别是当您的应用程序使用有效证书签名时。

string appFolder = Windows.ApplicationModel.Package.Current.InstalledLocation.Path;

嵌入您的资源

如上一节所述,强烈建议通过将“构建操作”更改为“嵌入式资源”并将“复制到输出目录”设置为“不复制”来嵌入 WPF 或 Winform 应用程序使用的图像资源,这样这些图像文件就不会在以后意外地被安装程序或“桌面应用转换器”(DAC)选中。

Embedded resource in Visual Studio

内联您的 OpenGL 着色器

可以使用 C++ 11 原始字符串字面量将 OpenGL 着色器代码内联到 C++ 源文件中,以避免从文本文件中保存和打开着色器。以下是 OpenGL 2.0 的顶点和像素着色器。

const char* vert_shader = R"vert(uniform mat4 WorldViewProjection;
attribute vec3 a_position;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main()
{
    gl_Position = WorldViewProjection * vec4(a_position, 1.0);
    v_texCoord = a_texCoord;
})vert";

const char* frag_shader = R"frag(varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main()
{
    vec4 color = texture2D( s_texture, v_texCoord );
    float alpha = clamp(1.0-color.r, 0.0, 1.0);
    if(v_texCoord.y <= 0.02)
        alpha = 0.0;
    color = vec4(0.0,0.0,0.0,alpha);
    gl_FragColor = color;
})frag";

内联您的 DirectX 着色器

可以在 Visual Studio 中指定编译、生成并将 DirectX 着色器二进制代码保存到头文件中的全局数组中。您可以通过包含头文件来访问该数组。文件名以 g_ 作为前缀,构成数组变量。我的着色器,在这里是一个像素着色器,名为 BackgroundPS,因此生成的头文件和变量分别是 BackgroundPS.hg_BackgroundPS

DirectX to output header

这是使用 ID3D11Device2::CreatePixelShader() 创建 g_BackgroundPS 着色器的方法。

#include "BackgroundPS.h"

// The g_BackgroundPS defined in BackgroundPS.h, 
// contains the pixel shader. g_BackgroundPS is binary byte array.

Microsoft::WRL::ComPtr<ID3D11PixelShader> pixelShader;
device->CreatePixelShader(g_BackgroundPS, sizeof(g_BackgroundPS), 
nullptr, pixelShader.ReleaseAndGetAddressOf())

桌面应用转换器

从 Microsoft Store 获取“桌面应用转换器”(DAC),并以管理员权限运行。我们将在应用程序文件夹上使用 DAC。DAC 也可以用于安装程序和引导程序,但在我的情况下,我的应用程序是新的,没有现有的安装程序。对于安装程序示例,我们改用“MSIX 打包工具”(MPT)。MPT 是制作应用程序包的推荐工具。我们使用 DAC 是因为它允许我们使用自签名证书安装应用程序,而 MPT 无法做到这一点。下面的命令行开关是不言自明的。-MakeAppx 表示制作 appx 安装程序,-Sign 表示生成自签名证书并用它对 appx 进行数字签名。

DesktopAppConverter.exe -Installer [Application folder] -AppExecutable [Executable Name] 
-Destination [Destination Folder] -PackageName [App Package Name] 
-Publisher [Publisher Name] -Version [App Version] -MakeAppx -Sign

以下是我使用 DAC 的示例及其结果输出。

PS C:\WINDOWS\System32> DesktopAppConverter.exe -Installer D:\MandyFrenzyApp\Release\ 
-AppExecutable MandyFrenzy.exe -Destination D:\Output -PackageName "MandyFrenzyApp" 
-Publisher "CN=WongShaoVoon" -Version 1.0.0.0 -MakeAppx -Sign

0
Output Paths:

Name                           Value
----                           -----
PackageFilesPath               D:\Output\MandyFrenzyApp\PackageFiles
MSIXPackageFilesPath
LogFilesPath                   D:\Output\MandyFrenzyApp\logs
CertPath                       D:\Output\MandyFrenzyApp\auto-generated.cer
AppxPackageFilesPath
PackagePath                    D:\Output\MandyFrenzyApp\MandyFrenzyApp.appx

如果 DAC 输出 0,则表示正常。在我们安装应用程序测试其运行情况之前,我们必须安装自签名证书。请按照说明安装证书。右键单击文件资源管理器中的 auto-generated.cer,调出上下文菜单,然后单击安装证书

证书导入向导出现。选择本地计算机选项。单击下一步

选择将所有证书放入以下存储选项。浏览以选择受信任的个人

查看设置并点击完成

您将看到导入成功

现在您可以在 MS Store 下安装您的应用程序,享受乐趣,看看是否有任何问题。

MSIX 打包工具

MSIX 打包工具 (MPT) 是微软官方推荐的 Win32 应用程序打包工具。在本节中,我们将演示如何使用 MPT 进行应用程序打包。MPT 的一个明显缺点是它只能打包已经带有安装程序的应用程序。如果您的应用程序是新的,就像我的情况一样,它没有现有的安装程序;您别无选择,只能制作一个安装程序,以便此工具为 MS Store 制作 MSIX 安装程序。MSIX 打包工具可以从 MS Store 免费下载。它要求 Windows 10 版本至少为 1809,否则它只会安装但无法执行。我尝试将我的 Windows 从 1803 更新到 1809,但那不是一个选项,我只能更新到最新的 1903(截至本文撰写时)。让我们开始运行 MPT。请事先禁用您的防病毒保护,以防止意外干扰。我们将看到这个欢迎屏幕,有 3 个选项。请点击“创建您的应用程序包”以继续。

在此创建新包页面,输入安装程序或引导程序的路径。将安装程序参数输入为“/q”。如果您有证书,请指定您的证书进行签名。如果您的 MSIX 没有数字签名,Windows 将不允许安装。有趣的是,要将您的应用程序提交到 Microsoft Store,您的 MSIX 安装程序不需要进行数字签名。

在第三页,我们可以选择在此计算机、远程计算机或本地虚拟机上创建包。我们将选择第一个选项。请记住,此时如果您的应用程序已安装在此电脑上,请先卸载它。

在第 4 页,我们输入包信息。如果您在第 2 页没有指定数字证书,可以输入任何“发布者名称”。您可以看到,我只输入了“包名称”和“发布者名称”,因为我不会提交此包。当您预留应用名称和注册开发者帐户时,Microsoft 会生成一个“包名称”和“发布者名称”,并在其前后添加随机字符。对于真实的提交,您必须使用 Microsoft 提供的那组“包名称”和“发布者名称”,否则提交将失败。问题在于数字证书,您无法更改“发布者名称”(灰色显示),它默认为证书中的名称,这与 Microsoft 提供的不一致。

在第 5 页,我们必须等待一段时间,让工具检测其驱动程序是否已安装以及 Windows 更新是否正在运行。您可以勾选 Windows 搜索并点击禁用选中项按钮来禁用 Windows 搜索。

在此页面上,未显示入口点。这是不可行的。入口点是您的可执行文件路径。未检测到您的可执行文件可能有 2 个原因;首先,在运行此工具之前未卸载您的应用程序,其次是您的防病毒软件 (AV) 干扰了安装程序操作,因此请暂时禁用 AV。点击刷新列表并浏览... 无助于解决问题。您必须重新启动工具并重新输入所有信息。点击上一步按钮无法解决或重新运行打包。

如果您的工具成功运行并完成,您将看到您的可执行文件作为入口点。

点击下一步按钮会询问您是否已完成。如果所有入口点都已检测到,请点击是,继续

现在,包已准备好保存。浏览到您的保存位置以保存包。您可以点击包编辑器在记事本中打开包 XML 文件以编辑一些信息。对于我的应用程序,我只是将处理器架构从 x64 更改为 x86。不确定为什么没有正确检测到。

现在包已完成,您可以安装以测试它或提交应用程序。为了增加成功提交的机会,您还需要做一步,那就是应用程序认证!这就是本文的下一节,也是最后一节。

应用认证

应用认证工具随 Visual Studio 安装的 Windows SDK 一起提供。确保您的应用以发布模式构建,并且应用程序文件夹中不存在 Windows.winmd。以管理员权限运行命令行提示符。

"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\"

使用前重置工具。

appcert.exe reset

命令参数可以如下。将目录更改到您的应用程序位置。

appcert.exe test -packagefullname [package full name] -reportoutputpath [report file name]

这是我的命令行示例

"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\appcert.exe" test 
-packagefullname MandyFrenzyApp -reportoutputpath c:\temp\test_report.xml

打开 XML 结果文件并检查 OVERALL_RESULTPASS 还是 FAIL。如果是 PASS,恭喜。如果不是,通过在 XML 中进一步搜索 FAIL 来缩小原因。失败可能有一个以上的原因。当 OPTIONAL="TRUE" 时,有些失败不会影响最终结果。如果您收到以下错误:“App 包清单应在 resources.pri 文件中定义有效的资源,根据 App 打包规范和 App 清单架构。”,这是正常的,因为我也有这个错误,并且此错误仅对 UWP 有效,而不是我的 WPF 应用程序,我无法生成 resources.pri 来通过此测试。我仍然继续提交我的应用程序,并且它被接受了。

历史

  • 2019 年 7 月 22 日:初始版本

《将你的...》系列的其他文章

© . All rights reserved.