包支持框架入门Get Started with Package Support Framework

包支持框架是一个开源工具包,可帮助你将修补程序应用于现有的桌面应用程序 (,而无需修改代码) 使其能够在 .msix 容器中运行。The Package Support Framework is an open source kit that helps you apply fixes to your existing desktop application (without modifying the code) so that it can run in an MSIX container. 包支持框架可帮助应用程序遵循新式运行时环境的最佳做法。The Package Support Framework helps your application follow the best practices of the modern runtime environment.

本文提供了有关包支持框架的每个组件的各异次,并逐步介绍了如何使用该组件。This article provides an indepth look at each component of Package Support Framework and step by step guide to using it.

了解包支持框架内的内容Understand what is inside a Package Support Framework

包支持框架包含一个可执行文件、一个运行时管理器 DLL 和一组运行时修复程序。The Package Support Framework contains an executable, a runtime manager DLL, and a set of runtime fixes.

包支持框架

过程如下:Here is the process:

  1. 创建一个配置文件,用于指定要应用于应用程序的修补程序。Create a configuration file that specifies the fixes that you want to apply to your application.
  2. 将包修改为指向包支持框架 (PSF) 启动器可执行文件。Modify your package to point to the Package Support Framework (PSF) launcher executable file.

当用户启动应用程序时,包支持框架启动器是运行的第一个可执行文件。When users starts your application, the Package Support Framework launcher is the first executable that runs. 该启动器将读取配置文件,并将运行时修复程序和运行时管理器 DLL 注入应用程序进程。It reads your configuration file and injects the runtime fixes and the runtime manager DLL into the application process. 如果应用程序需要使用该修复程序才能在 MSIX 容器中运行,则运行时管理器会应用该修复程序。The runtime manager applies the fix when it's needed by the application to run inside of an MSIX container.

包支持框架 DLL 注入

步骤1:识别打包的应用程序兼容性问题Step 1: Identify packaged application compatibility issues

首先,为应用程序创建包。First, create a package for your application. 然后,安装它,运行它并观察它的行为。Then, install it, run it, and observe its behavior. 收到的错误消息可能会帮助你识别兼容性问题。You might receive error messages that can help you identify a compatibility issue. 也可以使用进程监视器来识别问题。You can also use Process Monitor to identify issues. 常见问题与有关工作目录和程序路径权限的应用程序假设相关。Common issues relate to application assumptions regarding the working directory and program path permissions.

使用进程监视器识别问题Using Process Monitor to identify an issue

进程监视器 是一个功能强大的实用工具,用于观察应用的文件和注册表操作及其结果。Process Monitor is a powerful utility for observing an app's file and registry operations, and their results. 这可以帮助你了解应用程序的兼容性问题。This can help you to understand application compatibility issues. 打开进程监视器后,添加筛选器 (筛选器 > Filter ... ) 以便仅包括应用程序可执行文件中的事件。After opening Process Monitor, add a filter (Filter > Filter…) to include only events from the application executable.

Procmon 配合应用筛选器

将显示事件列表。A list of events will appear. 对于其中的许多事件,"结果" 列中将显示 "成功" 字样。For many of these events, the word SUCCESS will appear in the Result column.

Procmon 配合事件

或者,您可以将事件筛选为仅显示失败。Optionally, you can filter events to only show only failures.

Procmon 配合排除成功

如果你怀疑文件系统访问失败,请搜索 System32/SysWOW64 或包文件路径下的失败事件。If you suspect a filesystem access failure, search for failed events that are under either the System32/SysWOW64 or the package file path. 筛选器也可以在此处提供帮助。Filters can also help here, too. 从列表底部开始,向上滚动。Start at the bottom of this list and scroll upwards. 最近出现在此列表底部的失败。Failures that appear at the bottom of this list have occurred most recently. 请注意包含字符串(如 "拒绝访问" 和 "找不到路径/名称")的错误,并忽略看起来不可疑的问题。Pay most attention to errors that contain strings such as "access denied," and "path/name not found", and ignore things that don't look suspicious. PSFSample有两个问题。The PSFSample has two issues. 在下图中显示的列表中可以看到这些问题。You can see those issues in the list that appears in the following image.

Procmon 配合 Config.txt

在此图中出现的第一个问题中,应用程序无法从位于 "C:\Windows\SysWOW64" 路径中的 "Config.txt" 文件读取。In the first issue that appears in this image, the application is failing to read from the "Config.txt" file that is located in the "C:\Windows\SysWOW64" path. 应用程序不太可能尝试直接引用该路径。It's unlikely that the application is trying to reference that path directly. 大多数情况下,它会尝试使用相对路径从该文件中读取,默认情况下,"System32/SysWOW64" 是应用程序的工作目录。Most likely, it's trying to read from that file by using a relative path, and by default, "System32/SysWOW64" is the application's working directory. 这表明,应用程序需要将当前工作目录设置为包中的某个位置。This suggests that the application is expecting its current working directory to be set to somewhere in the package. 查看 appx 内部,可以看到该文件与可执行文件位于同一目录中。Looking inside of the appx, we can see that the file exists in the same directory as the executable.

应用 Config.txt

下图显示了第二个问题。The second issue appears in the following image.

Procmon 配合日志文件

在此问题中,应用程序无法将 .log 文件写入其包路径。In this issue, the application is failing to write a .log file to its package path. 这会建议使用文件重定向修复方法。This would suggest that a file redirection fixup might help.

步骤2:查找运行时修补程序Step 2: Find a runtime fix

PSF 包含可立即使用的运行时修补程序,如文件重定向修正。The PSF contains runtime fixes that you can use right now, such as the file redirection fixup.

文件重定向修正File Redirection Fixup

你可以使用 文件重定向修正 功能重定向尝试写入或读取目录中的数据,该目录无法从在 .msix 容器中运行的应用程序访问。You can use the File Redirection Fixup to redirect attempts to write or read data in a directory that isn't accessible from an application that runs in an MSIX container.

例如,如果你的应用程序写入到与你的应用程序可执行文件位于同一目录中的日志文件,则可以使用 文件重定向修正 功能在其他位置(例如本地应用数据存储)中创建该日志文件。For example, if your application writes to a log file that is in the same directory as your applications executable, then you can use the File Redirection Fixup to create that log file in another location, such as the local app data store.

社区中的运行时修补程序Runtime fixes from the community

请确保查看 GitHub 页面的社区贡献。Make sure to review the community contributions to our GitHub page. 其他开发人员可能会解决类似于你的问题并已共享运行时修复。It's possible that other developers have resolved an issue similar to yours and have shared a runtime fix.

步骤3:应用运行时修补程序Step 3: Apply a runtime fix

您可以使用 Windows SDK 中的一些简单工具来应用现有运行时修补程序,并通过执行以下步骤。You can apply an existing runtime fix with a few simple tools from the Windows SDK, and by following these steps.

  • 创建包布局文件夹Create a package layout folder
  • 获取包支持框架文件Get the Package Support Framework files
  • 将它们添加到包Add them to your package
  • 修改包清单Modify the package manifest
  • 创建配置文件Create a configuration file

让我们完成每个任务。Let's go through each task.

创建包布局文件夹Create the package layout folder

如果已 .msix (或 .appx) 文件,则可以将其内容解压缩到一个布局文件夹中,该文件夹将用作包的暂存区域。If you have a .msix (or .appx) file already, you can unpack its contents into a layout folder that will serve as the staging area for your package. 你可以在命令提示符下使用 Makeappx.exe 工具执行此操作,具体取决于 SDK 的安装路径,你可以在 Windows 10 电脑上找到 makeappx.exe 工具: x86: C:\Program Files (x86) \Windows Kits\10\bin\x86\makeappx.exe x64: C:\Program 文件 (x86) \Windows Kits\10\bin\x64\makeappx.exeYou can do this from a command prompt using MakeAppx tool, based on your installation path of the SDK, this is where you will find the makeappx.exe tool on your Windows 10 PC: x86: C:\Program Files (x86)\Windows Kits\10\bin\x86\makeappx.exe x64: C:\Program Files (x86)\Windows Kits\10\bin\x64\makeappx.exe

makeappx unpack /p PSFSamplePackage_1.0.60.0_AnyCPU_Debug.msix /d PackageContents

这会显示如下所示的内容。This will give you something that looks like the following.

包布局

如果没有 .msix (或 .appx) 文件,则可以从头开始创建包文件夹和文件。If you don't have a .msix (or .appx) file to start with, you can create the package folder and files from scratch.

获取包支持框架文件Get the Package Support Framework files

可以通过使用独立的 Nuget 命令行工具或通过 Visual Studio 获取 PSF Nuget 包。You can get the PSF Nuget package by using the standalone Nuget command line tool or via Visual Studio.

使用命令行工具获取包Get the package by using the command line tool

从以下位置安装 Nuget 命令行工具: https://www.nuget.org/downloadsInstall the Nuget command line tool from this location: https://www.nuget.org/downloads. 然后,在 Nuget 命令行中运行以下命令:Then, from the Nuget command line, run this command:

nuget install Microsoft.PackageSupportFramework

或者,可以将包扩展重命名为 .zip 并将其解压缩。Alternatively, you can rename the package extension to .zip and unzip it. 所需的所有文件都将位于/bin 文件夹下。All the files you need will be under the /bin folder.

使用 Visual Studio 获取包Get the package by using Visual Studio

在 Visual Studio 中,右键单击解决方案或项目节点,然后选择 "管理 Nuget 包" 命令之一。In Visual Studio, right-click your solution or project node and pick one of the Manage Nuget Packages commands. 搜索 " PackageSupportFramework " 或 " PSF " 以查找 Nuget.org 上的包。然后,安装它。Search for Microsoft.PackageSupportFramework or PSF to find the package on Nuget.org. Then, install it.

将包支持框架文件添加到包Add the Package Support Framework files to your package

将必需的32位和64位 PSF Dll 和可执行文件添加到包目录中。Add the required 32-bit and 64-bit PSF DLLs and executable files to the package directory. 使用下表作为指南。Use the following table as a guide. 还需要包含所需的任何运行时修补程序。You'll also want to include any runtime fixes that you need. 在我们的示例中,我们需要文件重定向运行时修复。In our example, we need the file redirection runtime fix.

应用程序可执行文件为 x64Application executable is x64 应用程序可执行文件为 x86Application executable is x86
PSFLauncher64.exePSFLauncher64.exe PSFLauncher32.exePSFLauncher32.exe
PSFRuntime64.dllPSFRuntime64.dll PSFRuntime32.dllPSFRuntime32.dll
PSFRunDll64.exePSFRunDll64.exe PSFRunDll32.exePSFRunDll32.exe

包内容现在应如下所示。Your package content should now look something like this.

包二进制文件

修改包清单Modify the package manifest

在文本编辑器中打开包清单,并将 Executable 元素的属性设置 Application 为 PSF 启动程序可执行文件的名称。Open your package manifest in a text editor, and then set the Executable attribute of the Application element to the name of the PSF Launcher executable file. 如果你知道目标应用程序的体系结构,请选择适当的版本,PSFLauncher32.exe 或 PSFLauncher64.exe。If you know the architecture of your target application, select the appropriate version, PSFLauncher32.exe or PSFLauncher64.exe. 否则,PSFLauncher32.exe 将适用于所有情况。If not, PSFLauncher32.exe will work in all cases. 示例如下。Here's an example.

<Package ...>
  ...
  <Applications>
    <Application Id="PSFSample"
                 Executable="PSFLauncher32.exe"
                 EntryPoint="Windows.FullTrustApplication">
      ...
    </Application>
  </Applications>
</Package>

创建配置文件Create a configuration file

创建文件名 config.json ,并将该文件保存到包的根文件夹。Create a file name config.json, and save that file to the root folder of your package. 修改文件上 config.js的已声明应用 ID,使其指向刚替换的可执行文件。Modify the declared app ID of the config.json file to point to the executable that you just replaced. 使用通过处理监视器获得的知识,还可以设置工作目录,并使用文件重定向修正将读取/写入操作重定向到包相对 "PSFSampleApp" 目录下的 .log 文件。Using the knowledge that you gained from using Process Monitor, you can also set the working directory as well as use the file redirection fixup to redirect reads/writes to .log files under the package-relative "PSFSampleApp" directory.

{
    "applications": [
        {
            "id": "PSFSample",
            "executable": "PSFSampleApp/PSFSample.exe",
            "workingDirectory": "PSFSampleApp/"
        }
    ],
    "processes": [
        {
            "executable": "PSFSample",
            "fixups": [
                {
                    "dll": "FileRedirectionFixup.dll",
                    "config": {
                        "redirectedPaths": {
                            "packageRelative": [
                                {
                                    "base": "PSFSampleApp/",
                                    "patterns": [
                                        ".*\\.log"
                                    ]
                                }
                            ]
                        }
                    }
                }
            ]
        }
    ]
}

下面是针对架构的 config.js指南:Following is a guide for the config.json schema:

ArrayArray keykey Value
applicationsapplications idid 使用 Id Application 包清单中元素的属性的值。Use the value of the Id attribute of the Application element in the package manifest.
applicationsapplications 可执行文件executable 要启动的可执行文件的包相对路径。The package-relative path to the executable that you want to start. 在大多数情况下,你可以在修改之前从包清单文件中获取此值。In most cases, you can get this value from your package manifest file before you modify it. 它是元素的属性的值 Executable ApplicationIt's the value of the Executable attribute of the Application element.
applicationsapplications workingDirectoryworkingDirectory (可选) 要用作启动的应用程序的工作目录的包相对路径。(Optional) A package-relative path to use as the working directory of the application that starts. 如果未设置此值,操作系统将使用 System32 目录作为应用程序的工作目录。If you don't set this value, the operating system uses the System32 directory as the application's working directory.
进程processes 可执行文件executable 在大多数情况下,这将是上面配置的名称, executable 其中包含已删除的路径和文件扩展名。In most cases, this will be the name of the executable configured above with the path and file extension removed.
修正fixups dlldll 要加载的链接地址的包相对路径,.msix/.appx。Package-relative path to the fixup, .msix/.appx to load.
修正fixups configconfig (可选) 控制修正 dll 的行为方式。(Optional) Controls how the fixup dll behaves. 此值的准确格式因修正链接而异,因为每个修正都可以根据需要解释此 "blob"。The exact format of this value varies on a fixup-by-fixup basis as each fixup can interpret this "blob" as it wants.

applicationsprocessesfixups 键是数组。The applications, processes, and fixups keys are arrays. 这意味着,可以使用文件 config.js来指定多个应用程序、进程和修复 DLL。That means that you can use the config.json file to specify more than one application, process, and fixup DLL.

打包并测试应用程序Package and test the app

接下来,创建一个包。Next, create a package.

makeappx pack /d PackageContents /p PSFSamplePackageFixup.msix

然后,对其进行签名。Then, sign it.

signtool sign /a /v /fd sha256 /f ExportedSigningCertificate.pfx PSFSamplePackageFixup.msix

有关详细信息,请参阅 如何创建包签名证书如何使用 signtool 为包签名For more information, see how to create a package signing certificate and how to sign a package using signtool

使用 PowerShell 安装包。Using PowerShell, install the package.

备注

请记得首先卸载包。Remember to uninstall the package first.

powershell Add-AppPackage .\PSFSamplePackageFixup.msix

运行应用程序,并在应用运行时修补程序时观察行为。Run the application and observe the behavior with runtime fix applied. 根据需要重复诊断和打包步骤。Repeat the diagnostic and packaging steps as necessary.

检查包支持框架是否正在运行Check whether the Package Support Framework is running

您可以检查运行时修复程序是否正在运行。You can check whether your runtime fix is running. 执行此操作的一种方法是打开 任务管理器 ,然后单击 " 更多详细信息"。A way to do this is to open Task Manager and click More details. 找到应用包支持框架的应用,并展开应用详细信息以视图更多详细信息。Find the app that the package support framework was applied to and expand the app detail to veiw more details. 你应能够查看包支持框架是否正在运行。You should be able to view that the Package Support Framework is running.

使用跟踪修正Use the Trace Fixup

诊断打包应用程序兼容性问题的一种替代方法是使用跟踪修正。An alternative technique to diagnosing packaged application compatibility issues is to use the Trace Fixup. 此 DLL 包含在 PSF 中,并提供应用程序行为的详细诊断视图,类似于进程监视器。This DLL is included with the PSF and provides a detailed diagnostic view of the app's behavior, similar to Process Monitor. 它专门设计用于显示应用程序兼容性问题。It is specially designed to reveal application compatibility issues. 若要使用跟踪修正,请将 DLL 添加到包,将以下片段添加到 config.js上的,然后打包并安装应用程序。To use the Trace Fixup, add the DLL to the package, add the following fragment to your config.json, and then package and install your application.

{
    "dll": "TraceFixup.dll",
    "config": {
        "traceLevels": {
            "filesystem": "allFailures"
        }
    }
}

默认情况下,跟踪修正将筛选出可能被视为 "预期" 的失败。By default, the Trace Fixup filters out failures that might be considered "expected". 例如,应用程序可能会尝试无条件删除文件,而不检查其是否已存在,并忽略结果。For example, applications might try to unconditionally delete a file without checking to see if it already exists, ignoring the result. 这会导致某些意外的失败被筛选掉,因此,在上述示例中,我们选择接收来自文件系统功能的所有失败。This has the unfortunate consequence that some unexpected failures might get filtered out, so in the above example, we opt to receive all failures from filesystem functions. 我们这样做的原因是,在尝试从 Config.txt 文件中读取消息失败,并显示消息 "找不到文件"。We do this because we know from before that the attempt to read from the Config.txt file fails with the message "file not found". 这是一种通常会出现的错误,通常不会被认为是意外情况。This is a failure that is frequently observed and not generally assumed to be unexpected. 在实践中,可能最好仅开始筛选意外故障,然后在出现仍无法确定的问题时回退到所有失败。In practice it's likely best to start out filtering only to unexpected failures, and then falling back to all failures if there's an issue that still can't be identified.

默认情况下,跟踪修正的输出将发送到附加的调试器。By default, the output from the Trace Fixup gets sent to the attached debugger. 在此示例中,我们不会附加调试器,而是使用 SysInternals 中的 DebugView 程序来查看其输出。For this example, we aren't going to attach a debugger, and will instead use the DebugView program from SysInternals to view its output. 运行应用程序后,可以看到与之前相同的故障,这会使我们向相同的运行时修复。After running the app, we can see the same failures as before, which would point us towards the same runtime fixes.

找不到 TraceShim 文件

拒绝访问 TraceShim

调试、扩展或创建运行时修补程序Debug, extend, or create a runtime fix

你可以使用 Visual Studio 来调试运行时修补程序,扩展运行时修补程序,或者从头开始创建一个修补程序。You can use Visual Studio to debug a runtime fix, extend a runtime fix, or create one from scratch. 你需要执行这些操作才能成功。You'll need to do these things to be successful.

  • 添加打包项目Add a packaging project
  • 为运行时修复添加项目Add project for the runtime fix
  • 添加启动 PSF 启动器可执行文件的项目Add a project that starts the PSF Launcher executable
  • 配置打包项目Configure the packaging project

完成后,解决方案将如下所示。When you're done, your solution will look something like this.

已完成解决方案

让我们看看此示例中的每个项目。Let's look at each project in this example.

ProjectProject 目的Purpose
DesktopApplicationPackageDesktopApplicationPackage 此项目基于 Windows 应用程序打包项目 ,并输出 .msix 包。This project is based on the Windows Application Packaging project and it outputs the MSIX package.
RuntimefixRuntimefix 这是一个 c + + 动态链接库项目,其中包含一个或多个用于运行时修复的替换函数。This is a C++ Dynamic-Linked Library project that contains one or more replacement functions that serve as the runtime fix.
PSFLauncherPSFLauncher 这是 c + + 空项目。This is C++ Empty Project. 此项目是用于收集包支持框架的运行时可分发文件的位置。This project is a place to collect the runtime distributable files of the Package Support Framework. 它输出可执行文件。It outputs an executable file. 该可执行文件是在启动解决方案时运行的第一件事。That executable is the first thing that runs when you start the solution.
WinFormsDesktopApplicationWinFormsDesktopApplication 此项目包含桌面应用程序的源代码。This project contains the source code of a desktop application.

若要查看包含所有这些类型项目的完整示例,请参阅 PSFSampleTo look at a complete sample that contains all of these types of projects, see PSFSample.

让我们逐步完成在解决方案中创建和配置这些项目的步骤。Let's walk through the steps to create and configure each of these projects in your solution.

创建包解决方案Create a package solution

如果还没有适用于桌面应用程序的解决方案,请在 Visual Studio 中创建一个新的 空白解决方案If you don't already have a solution for your desktop application, create a new Blank Solution in Visual Studio.

空白解决方案

你可能还需要添加任何应用程序项目。You may also want to add any application projects you have.

添加打包项目Add a packaging project

如果还没有 Windows 应用程序打包项目,请创建一个项目并将其添加到解决方案中。If you don't already have a Windows Application Packaging Project, create one and add it to your solution.

包项目模板

有关 Windows 应用程序打包项目的详细信息,请参阅 使用 Visual Studio 打包你的应用程序For more information on Windows Application Packaging project, see Package your application by using Visual Studio.

解决方案资源管理器中,右键单击打包项目,选择 " 编辑",然后将其添加到项目文件的底部:In Solution Explorer, right-click the packaging project, select Edit, and then add this to the bottom of the project file:

<Target Name="PSFRemoveSourceProject" AfterTargets="ExpandProjectReferences" BeforeTargets="_ConvertItems">
<ItemGroup>
  <FilteredNonWapProjProjectOutput Include="@(_FilteredNonWapProjProjectOutput)">
  <SourceProject Condition="'%(_FilteredNonWapProjProjectOutput.SourceProject)'=='<your runtime fix project name goes here>'" />
  </FilteredNonWapProjProjectOutput>
  <_FilteredNonWapProjProjectOutput Remove="@(_FilteredNonWapProjProjectOutput)" />
  <_FilteredNonWapProjProjectOutput Include="@(FilteredNonWapProjProjectOutput)" />
</ItemGroup>
</Target>

为运行时修复添加项目Add project for the runtime fix

将 c + + **动态链接库 (DLL) ** 项目添加到解决方案。Add a C++ Dynamic-Link Library (DLL) project to the solution.

运行时修复库

右键单击该项目,然后选择 " 属性"。Right-click the that project, and then choose Properties.

在属性页中,找到 " c + + 语言标准 " 字段,然后在该字段旁边的下拉列表中,选择 " **ISO c + + 17 标准 (/std: c + + 17) ** " 选项。In the property pages, find the C++ Language Standard field, and then in the drop-down list next to that field, select the ISO C++17 Standard (/std:c++17) option.

ISO 17 选项

右键单击该项目,然后在上下文菜单中,选择 " 管理 Nuget 包 " 选项。Right-click that project, and then in the context menu, choose the Manage Nuget Packages option. 确保 " 包源 " 选项设置为 " 全部 " 或 " nuget.org"。Ensure that the Package source option is set to All or nuget.org.

单击 "设置" 图标旁边的字段。Click the settings icon next that field.

搜索 PSF* Nuget 包,并将其安装到此项目中。Search for the PSF* Nuget package, and then install it for this project.

NuGet 包

如果你想要调试或扩展现有的运行时修补程序,请添加你使用本指南的 查找运行时修补程序 部分中所述的指导来获取的运行时修补文件。If you want to debug or extend an existing runtime fix, add the runtime fix files that you obtained by using the guidance described in the Find a runtime fix section of this guide.

如果你打算创建全新的修补程序,请不要将任何内容添加到此项目。If you intend to create a brand new fix, don't add anything to this project just yet. 稍后在本指南中,我们将帮助你向此项目添加正确的文件。We'll help you add the right files to this project later in this guide. 现在,我们将继续设置您的解决方案。For now, we'll continue setting up your solution.

添加启动 PSF 启动器可执行文件的项目Add a project that starts the PSF Launcher executable

向解决方案中添加一个 c + + 空项目 项目。Add a C++ Empty Project project to the solution.

空项目

使用上一节中所述的相同指南,将 PSF Nuget 包添加到此项目中。Add the PSF Nuget package to this project by using the same guidance described in the previous section.

打开该项目的属性页,然后在 " 常规 设置" 页中,将 " 目标名称 " 属性设置为 PSFLauncher32 或, PSFLauncher64 具体取决于应用程序的体系结构。Open the property pages for the project, and in the General settings page, set the Target Name property to PSFLauncher32 or PSFLauncher64 depending on the architecture of your application.

PSF 启动器引用

将项目引用添加到解决方案中的运行时修复项目。Add a project reference to the runtime fix project in your solution.

运行时修复引用

右键单击该引用,然后在 " 属性 " 窗口中应用这些值。Right-click the reference, and then in the Properties window, apply these values.

propertiesProperty Value
复制本地Copy local TrueTrue
复制本地附属程序集Copy Local Satellite Assemblies TrueTrue
引用程序集输出Reference Assembly Output TrueTrue
链接库依赖项Link Library Dependencies 错误False
链接库依赖项输入Link Library Dependency Inputs 错误False

配置打包项目Configure the packaging project

在打包项目中,右键单击应用程序文件夹,然后选择添加引用In the packaging project, right-click the Applications folder, and then choose Add Reference.

添加项目引用

选择 PSF 启动器项目和桌面应用程序项目,然后选择 "确定" 按钮。Choose the PSF Launcher project and your desktop application project, and then choose the OK button.

桌面项目

备注

如果你的应用程序没有源代码,只需选择 PSF 启动器项目即可。If you don't have the source code to your application, just choose the PSF Launcher project. 当你创建配置文件时,我们将向你展示如何引用可执行文件。We'll show you how to reference your executable when you create a configuration file.

在 " 应用程序 " 节点中,右键单击 PSF 启动器应用程序,然后选择 " 设置为入口点"。In the Applications node, right-click the PSF Launcher application, and then choose Set as Entry Point.

设置入口点

向打包项目添加一个名为的文件 config.json ,然后将以下 json 文本复制并粘贴到该文件中。Add a file named config.json to your packaging project, then, copy and paste the following json text into the file. 将 " 包操作 " 属性设置为 " 内容"。Set the Package Action property to Content.

{
    "applications": [
        {
            "id": "",
            "executable": "",
            "workingDirectory": ""
        }
    ],
    "processes": [
        {
            "executable": "",
            "fixups": [
                {
                    "dll": "",
                    "config": {
                    }
                }
            ]
        }
    ]
}

为每个键提供一个值。Provide a value for each key. 使用此表作为指南。Use this table as a guide.

ArrayArray keykey Value
applicationsapplications idid 使用 Id Application 包清单中元素的属性的值。Use the value of the Id attribute of the Application element in the package manifest.
applicationsapplications 可执行文件executable 要启动的可执行文件的包相对路径。The package-relative path to the executable that you want to start. 在大多数情况下,你可以在修改之前从包清单文件中获取此值。In most cases, you can get this value from your package manifest file before you modify it. 它是元素的属性的值 Executable ApplicationIt's the value of the Executable attribute of the Application element.
applicationsapplications workingDirectoryworkingDirectory (可选) 要用作启动的应用程序的工作目录的包相对路径。(Optional) A package-relative path to use as the working directory of the application that starts. 如果未设置此值,操作系统将使用 System32 目录作为应用程序的工作目录。If you don't set this value, the operating system uses the System32 directory as the application's working directory.
进程processes 可执行文件executable 在大多数情况下,这将是上面配置的名称, executable 其中包含已删除的路径和文件扩展名。In most cases, this will be the name of the executable configured above with the path and file extension removed.
修正fixups dlldll 要加载的链接地址 DLL 的包相对路径。Package-relative path to the fixup DLL to load.
修正fixups configconfig (可选) 控制修正 DLL 的行为方式。(Optional) Controls how the fixup DLL behaves. 此值的准确格式因修正链接而异,因为每个修正都可以根据需要解释此 "blob"。The exact format of this value varies on a fixup-by-fixup basis as each fixup can interpret this "blob" as it wants.

完成后, config.json 文件将如下所示。When you're done, your config.json file will look something like this.

{
  "applications": [
    {
      "id": "DesktopApplication",
      "executable": "DesktopApplication/WinFormsDesktopApplication.exe",
      "workingDirectory": "WinFormsDesktopApplication"
    }
  ],
  "processes": [
    {
      "executable": ".*App.*",
      "fixups": [ { "dll": "RuntimeFix.dll" } ]
    }
  ]
}

备注

applicationsprocessesfixups 键是数组。The applications, processes, and fixups keys are arrays. 这意味着,可以使用文件 config.js来指定多个应用程序、进程和修复 DLL。That means that you can use the config.json file to specify more than one application, process, and fixup DLL.

调试运行时修补程序Debug a runtime fix

在 Visual Studio 中,按 F5 启动调试器。In Visual Studio, press F5 to start the debugger. 第一件事是 PSF 启动器应用程序,该应用程序随后会启动目标桌面应用程序。The first thing that starts is the PSF Launcher application, which in turn, starts your target desktop application. 若要调试目标桌面应用程序,必须通过选择 " 调试"->"附加到进程",然后选择应用程序进程,手动附加到桌面应用程序进程。To debug the target desktop application, you'll have to manually attach to the desktop application process by choosing Debug->Attach to Process, and then selecting the application process. 若要允许使用本机运行时修复 DLL 调试 .NET 应用程序,请选择 "托管和本机代码类型" (混合模式调试 ") 。To permit the debugging of a .NET application with a native runtime fix DLL, select managed and native code types (mixed mode debugging).

完成此设置后,可以在桌面应用程序代码和运行时修复项目中的代码行旁边设置断点。Once you've set this up, you can set break points next to lines of code in the desktop application code and the runtime fix project. 如果你的应用程序没有源代码,则只能在运行时修复项目中的代码行旁边设置断点。If you don't have the source code to your application, you'll be able to set break points only next to lines of code in your runtime fix project.

由于 F5 调试通过从包布局文件夹路径部署松散文件来运行应用程序,而不是从 .msix/.appx 包进行安装,因此布局文件夹通常与已安装的包文件夹具有相同的安全限制。Because F5 debugging runs the application by deploying loose files from the package layout folder path, rather than installing from a .msix/.appx package, the layout folder typically does not have the same security restrictions as an installed package folder. 因此,在应用运行时修补程序之前,可能无法重现包路径访问拒绝错误。As a result, it may not be possible to reproduce package path access denial errors prior to applying a runtime fix.

若要解决此问题,请使用 .msix/.appx 包部署,而不是按 F5 松散文件部署。To address this issue, use .msix / .appx package deployment rather than F5 loose file deployment. 如前文所述,若要创建 .msix/.appx 包文件,请使用 Windows SDK 中的 makeappx.exe 实用程序。To create a .msix / .appx package file, use the MakeAppx utility from the Windows SDK, as described above. 或者,在 Visual Studio 中,右键单击应用程序项目节点,然后选择 " 存储-> 创建应用包"。Or, from within Visual Studio, right-click your application project node and select Store -> Create App Packages.

Visual Studio 的另一个问题是,它没有为附加到调试器启动的任何子进程提供内置支持。Another issue with Visual Studio is that it does not have built-in support for attaching to any child processes launched by the debugger. 这使得难以在目标应用程序的启动路径中调试逻辑,必须在启动后由 Visual Studio 手动附加。This makes it difficult to debug logic in the startup path of the target application, which must be manually attached by Visual Studio after launch.

若要解决此问题,请使用支持子进程附加的调试程序。To address this issue, use a debugger that supports child process attach. 请注意,通常不能将实时 (JIT) 调试器附加到目标应用程序。Note that it is generally not possible to attach a just-in-time (JIT) debugger to the target application. 这是因为大多数 JIT 技术都涉及到通过 ImageFileExecutionOptions 注册表项启动调试器来代替目标应用。This is because most JIT techniques involve launching the debugger in place of the target app, via the ImageFileExecutionOptions registry key. 这会使 PSFLauncher.exe 将 FixupRuntime.dll 注入到目标应用中,这种机制将违背 detouring 机制。This defeats the detouring mechanism used by PSFLauncher.exe to inject FixupRuntime.dll into the target app. WinDbg 包含在 Windows 调试工具中,并从 Windows SDK获取,它支持子进程附加。WinDbg, included in the Debugging Tools for Windows, and obtained from the Windows SDK, supports child process attach. 它现在还支持直接 启动和调试 UWP 应用It also now supports directly launching and debugging a UWP app.

若要将目标应用程序启动调试为子进程,请启动 WinDbgTo debug target application startup as a child process, start WinDbg.

windbg.exe -plmPackage PSFSampleWithFixup_1.0.59.0_x86__7s220nvg1hg3m -plmApp PSFSample

WinDbg 提示符下,启用子调试并设置相应的断点。At the WinDbg prompt, enable child debugging and set appropriate breakpoints.

.childdbg 1
g

在目标应用程序启动并中断到调试器之前, (执行) (execute until target application starts and breaks into the debugger)

sxe ld fixup.dll
g

(执行,直到加载了修复 DLL) (execute until the fixup DLL is loaded)

bp ...

备注

PLMDebug 也可用于在启动时将调试程序附加到应用程序,并且也包含在 Windows 调试工具中。PLMDebug can be also used to attach a debugger to an app upon launch, and is also included in the Debugging Tools for Windows. 不过,使用的直接支持比 WinDbg 提供的直接支持更复杂。However, it is more complex to use than the direct support now provided by WinDbg.

支持Support

有问题?Have questions? 请在 .MSIX 技术社区网站上的 " 包支持框架 " 会话空间询问我们。Ask us on the Package Support Framework conversation space on the MSIX tech community site.