实验室 1g:生成零售版映像
我们将详细说明创建零售 Windows IoT 核心版映像并将其刷写到特定硬件设备所要执行的步骤。
先决条件/要求
确保已根据创建基本映像所述创建了基本映像,并完成了先前的所有实验。
需要安装以下工具才能完成本部分:
- 零售代码签名证书
- 交叉签名证书
- Visual Studio
- Windows 评估和部署工具包 (Windows ADK)
- IoT 核心版 PowerShell 环境
- 一个文本编辑器,例如记事本或 VS Code
修改项目配置文件
按照以下步骤添加要包含在零售映像中的任何自定义应用程序或预配程序包。
- 若要添加自定义应用程序,应按照将应用添加到映像中列出的说明操作。 但是,在执行 Add-IoTProductFeature 命令时,需要指定
Retail
而不是Test
,如下所示:
Add-IoTProductFeature ProductX Retail APPX_HELLOWORLDAPP -OEM
or addfid ProductX Retail APPX_HELLOWORLDAPP -OEM
这会将名为 APPX_HELLOWORLDAPP 的 FeatureID 添加到指定产品的零售 OEMInput XML 文件。
- 请尽量减少要包含的 Windows IoT 核心版功能。 另外,建议删除 Windows IoT 核心版测试映像中默认包含的任何测试应用程序。 这包括 IoT 核心版默认应用程序,以及任何其他开发人员工具或测试功能。 为此,可以使用 Remove-IoTProductFeature:
Remove-IoTProductFeature ProductX Test IOT_BERTHA
or removefid ProductX Test IOT_BERTHA
正确添加应用程序并为其签名
如果你有一个或多个要包含在 Windows IoT 核心版零售映像中的自定义应用程序,则需要验证在将这些应用程序添加到零售映像中时它们是否已正确签名。 对于要包含在映像中的每个应用程序,请执行以下步骤。 请注意,如果只需包含一个应用程序,则可以跳过步骤 8 和 9。
在技术人员电脑上安装零售代码签名证书。
在 Visual Studio 中打开你的自定义应用程序,然后打开 Package.appxmanifest 文件。
单击“打包”选项卡,然后单击“选择证书...”按钮。
- 出现的对话框将显示用于代码签名的证书。 单击“配置证书...”下拉菜单,然后选择“从证书存储中选择...”:
出现提示时选择你的零售代码签名证书,然后单击“确定”。
在 Visual Studio 中保存项目,然后生成 Appx 包。 请注意,在生成此包时,系统会提示你输入零售代码签名证书的密码。
生成 Appx 文件后,在 IoT 核心版 Powershell 环境中运行以下命令:
Add-IoTAppxPackage "C:\Dev\OpenSource\ContosoApp\ContosoApp\AppPackages\ContosoApp_1.0.0.0_ARM_Debug_Test\ContosoApp_1.0.0.0_ARM_Debug.appx" fga Appx.ContosoApp
(or) newAppxPkg "C:\Dev\OpenSource\ContosoApp\ContosoApp\AppPackages\ContosoApp_1.0.0.0_ARM_Debug_Test\ContosoApp_1.0.0.0_ARM_Debug.appx" fga Appx.ContosoApp
生成零售映像文件
为所有自定义应用程序包正确签名后,接下来可以生成 Windows IoT 核心版零售映像。 在执行以下步骤之前,请验证电脑上是否安装了零售代码签名证书:
- 设置 IoT 签名,以包含有关证书和交叉证书的详细信息。 为此,可以修改工作区(例如 C:\MyWorkspace)中的
IoTWorkspace.xml
文件:
<!--Specify the retail signing certificate details, Format given below -->
<RetailSignToolParam>/s my /sha1 "thumbprint" /fd SHA256 /ac "c:\DownloadedCrossCert.crt"</RetailSignToolParam>
以管理员身份运行 IoT 核心版 PowerShell 环境。
设置零售签名的环境。 使用 Set-IoTRetailSign 执行此操作:
Set-IoTRetailSign On
(or) retailsign on
- 生成包:
New-IoTCabPackage All
(or) buildpkg all
生成所有包 .CAB 文件后,应验证其中的每个文件是否已通过零售证书正确签名。 如果某些文件仍旧是通过测试证书签名的(如果使用技术人员电脑来生成测试和零售映像,则通常存在这种情况),你可以使用 Redo-IoTCabSignature 重新为这些文件签名:
Redo-IoTCabSignature C:\BSP.IN C:\BSP.OUT
(or) re-sign.cmd C:\BSP.IN C:\BSP.OUT
这会从 c:\BSP.IN
提取 .CAB 文件,使用零售证书将其重新签名,然后将其复制到 c:\BSP.OUT
目录。
如果在步骤 5 中已将 .CAB 文件重新签名,请将已重新签名的 .CAB 文件复制到
C:\IoT\Workspaces\ContosoWS\Build\<arch>\pkgs
并覆盖现有文件。 在本示例中,这些文件将复制到C:\IoT\Workspaces\ContosoWS\Build\arm\pkgs
。运行以下命令生成零售映像:
New-IoTFFUImage ProductX Retail
(or)buildimage ProductX Retail
- 然后,可以按照刷写映像中的说明刷写零售映像。
使用的命令
下面按顺序列出了用于创建零售 IoT 核心版映像的命令。 请注意,应先安装零售代码签名证书。在为 .CAB 文件重新签名时,系统可能会提示你输入证书密码。
Set-IoTRetailSign On
New-IoTCabPackage All
Redo-IoTCabSignature C:\BSP.IN C:\BSP.OUT
xcopy C:\BSP.OUT\*.cab C:\IoT\Workspaces\ContosoWS\Build\arm\pkgs\*.cab
New-IoTFFUImage ProductX Retail
将功能添加到零售配置
使用 Add-IoTProductFeature 更新产品零售配置文件
# Add application features Add-IoTProductFeature ProductA Test APPX_MYUWPAPP -OEM Remove-IoTProductFeature ProductA Test IOT_BERTHA # Add registry and file features Add-IoTProductFeature ProductA Retail FILES_CONFIGS -OEM Add-IoTProductFeature ProductA Retail REGISTRY_SETTINGS -OEM # Add provisioning feature Add-IoTProductFeature ProductA Retail PROV_WIFISETTINGS -OEM # Add driver Add-IoTProductFeature ProductA Retail DRIVERS_HELLOBLINKY -OEM
验证零售映像
用户只需打开刷入了映像的设备,即可轻松验证 Windows IoT 核心版的自定义测试映像。 设备运行后,你可以运行各项检查来验证该设备是否确实正常运行。 这些测试的难度取决于映像中引入的安全因素的级别。 由于测试映像中没有内置安全协议,因此可以使用所有可用的开发工具来测试 IoT 设备。
对于 Windows IoT 核心版的自定义零售映像,测试任务更加困难,因为你可能会将安全协议包含为要安装到设备的映像的一部分。 由于这些安全协议的性质,你可能无法使用可用的测试工具来验证设备,因此可能需要编写一个可在 IoT 设备上运行的测试应用程序。 然后,此应用程序将对 IoT 设备的各个区域和功能执行验证测试。
可通过以下方式之一对 Windows IoT 核心版的自定义零售映像进行测试:
干净的零售映像
如果你确实想要一个干净的零售映像,则需要为设备创建两个零售映像。 这两个映像是相同的,只不过其中一个映像包含测试应用程序(配置为前台应用程序),而另一个“干净的”映像则不包含。 你将刷写第一个映像(包括测试应用程序),并在 IoT 设备上执行测试验证。 验证后,可以使用第二个“干净的”零售映像重新刷写 IoT 设备以进行分发。
优点:最终的零售映像是完全干净的,其中只包含被视为必要的项。
缺点:在零售映像中包含测试应用程序可能会在预配程序包中造成某些潜在问题,并且测试应用程序中可能发生用户错误。 这会使得该零售映像与最终零售映像不同。
一次性直通测试
仅创建一个最终零售映像,其中也包含测试应用程序。 你将配置映像,以便在启动开箱即用体验 (OOBE) 应用程序后启动测试应用程序(作为前台应用程序)。 将触发测试应用程序中的条件语句,使应用程序知道它之前运行过一次(防止它在设备首次开机后运行)。
// Declare variable
Windows.Storage.ApplicationDataContainer localSettings =
Windows.Storage.ApplicationData.Current.LocalSettings;
// Set variable as boolean, numbers, or string values as needed at approperiate location within the test app
localSettings.Values["appRanOnce"] = false;
// Read variable and verify value to check and apply logic
Object value = localSettings.Values["appRanOnce"];
注意
为获取最佳结果,请仅使用 localSettings
来存储变量,以存储设置值。 使用 roamingSettings
功能有可能会导致不良结果。
localSettings
在撰写本文时,只能保存 64k 数据。 在此处详细了解应用程序设置。
使用上面的代码块,可以在启动测试应用程序时应用逻辑,以便在后续启动时该应用程序执行适当的操作。
我可以执行哪些类型的操作?
- 启动另一个 FGA 应用
- 编辑注册表以修改启动顺序
从测试应用程序启动另一个 FGA 应用程序
如果你要启动 Microsoft Store 应用,可以使用以下代码片段来启动通过 Store 安装和更新的应用。 可在此处找到有关 URI 方案的更多信息。
// Following will launch the Microsoft store app and navigate to the Games section
bool result = await Windows.System.Launcher.LaunchUriAsync(new Uri
("ms-windows-store://navigatetopage/?Id=Games"));
// Following will launch the One Note app using the package family name (PFN)
bool result = await Windows.System.Launcher.LaunchUriAsync(new Uri
("ms-windows-store://pdp/?PFN= Microsoft.Office.OneNote_8wekyb3d8bbwe"));
如果你要启动自定义(非 Microsoft Store)应用,可以通过 AppServiceConnection
启动使用包系列名称 (PFN) 的应用。
首先,必须将最终应用 (com.concurrency.lwinsapp) 注册到系统中的应用服务。 需要修改 Package.appxmanifest file
,以在清单的 <Applications>
节中包含以下代码块。
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="AppServiceProvider.App">
<Extensions>
<uap:Extension Category="windows.appService" EntryPoint="MyAppService.AppLaunchService">
<uap3:AppService Name="com.concurrency.lwinsapp" uap4:SupportsMultipleInstances="true" />
</uap:Extension>
</Extensions>
...
</Application>
以下代码段将启动一个自定义应用程序:
private AppServiceConnection appLaunchService;
...
this.appLaunchService = new AppServiceConnection();
this.appLaunchService.AppServiceName = "com.concurrency.lwinsapp";
this.appLaunchService.PackageFamilyName = "f3a114f7-e099-4773-8c93-77abcba14f62_004hcn5rxyy0y";
var status = await this.appLaunchService.OpenAsync();
通过组合 localSettings
与 AppServiceConnection
之间的逻辑,可以在每次启动设备时绕过测试应用程序。 本质上,测试应用程序在每次启动时都会运行,但在启动时会“直通”到最终应用程序。 如果需要,可按以下方式设置逻辑:如果测试应用程序的测试失败,设备将不继续运行最终应用程序。 如果需要验证设备是否经过全面测试并且在每次启动时都正常运行,则这种设置方式可能会有帮助。
优点:可以在每次启动时自动测试设备,以确保正确设置某些条件并且设备经过全面测试(且安全)。
缺点:在零售映像中包含测试应用程序。 应用程序可能有安全漏洞。 请确保可按需锁定测试应用。 由于测试应用程序的性质,你也许可以修改设备的功能。