如果没有可以解决问题的运行时问题解决方案,可以编写替代函数,并包括任何相关的配置数据以创建新的运行时解决方案。 让我们看看每个部分。
替换函数
首先,确定应用程序在 MSIX 容器中运行时哪个函数调用失败。 然后,您可以创建希望运行时管理器调用的替换函数。 这使你有机会将函数的实现替换为符合新式运行时环境规则的行为。
声明 FIXUP_DEFINE_EXPORTS 宏,然后在每个要添加运行时修补程序函数的 .CPP 文件的顶部添加 fixup_framework.h 的 include 语句。
#define FIXUP_DEFINE_EXPORTS
#include <fixup_framework.h>
重要
请确保宏 FIXUP_DEFINE_EXPORTS 显示在 include 语句之前。
创建一个函数,该函数的签名与要修改的行为相同。 下面是替换函数 MessageBoxW 的示例函数。
auto MessageBoxWImpl = &::MessageBoxW;
int WINAPI MessageBoxWFixup(
_In_opt_ HWND hwnd,
_In_opt_ LPCWSTR,
_In_opt_ LPCWSTR caption,
_In_ UINT type)
{
return MessageBoxWImpl(hwnd, L"SUCCESS: This worked", caption, type);
}
DECLARE_FIXUP(MessageBoxWImpl, MessageBoxWFixup);
对DECLARE_FIXUP的调用将MessageBoxW函数映射到您的新替换函数。 当应用程序尝试调用函数 MessageBoxW 时,它将改为调用替换函数。
防止对运行时修复中的函数进行递归调用
reentrancy_guard可将类型添加到函数中,以防止递归函数调用。
例如,您可以为CreateFile函数生成一个替代函数。 你的实现可能会调用 CopyFile 函数,但该函数的 CopyFile 实现可能会调用该 CreateFile 函数。 这可能会导致对 CreateFile 函数的无限递归循环调用。
有关 reentrancy_guard 的详细信息,请查看 authoring.md
配置数据
如果要将配置数据添加到你的运行时修改中,请考虑将其添加到config.json中。 这样,就可以使用该 FixupQueryCurrentDllConfig 方法来轻松分析该数据。 此示例分析该配置文件中的布尔值和字符串值。
if (auto configRoot = ::FixupQueryCurrentDllConfig())
{
auto& config = configRoot->as_object();
if (auto enabledValue = config.try_get("enabled"))
{
g_enabled = enabledValue->as_boolean().get();
}
if (auto logPathValue = config.try_get("logPath"))
{
g_logPath = logPathValue->as_string().wstring();
}
}
修正元数据
每个修复和 PSF 启动器应用程序都有一个 XML 元数据文件,其中包含以下信息:
- Version:PSF 的版本采用 MAJOR.MINOR.PATCH 格式,遵循语义版本 2 的规范。
- 最低 Windows 平台:修复或 PSF 启动器所需的最低 Windows 版本。
- Description:修正的简短说明。
- WhenToUse:关于何时应该应用该修正的经验法则。
有关示例,请参阅重定向修复的 FileRedirectionFixupMetadata.xml 元数据文件。 此处 提供了元数据架构。