适用于 BinaryFormatter 的 Windows Forms 迁移指南

移除 BinaryFormatter

从 .NET 9 开始,BinaryFormatter 不再受支持,因为它存在已知的安全风险,而且它的 API 总是为所有项目类型抛出 PlatformNotSupportedException,包括 Windows Forms 应用。 有关 BinaryFormatter 带来的风险以及移除它的原因的详细信息,请参阅 BinaryFormatter 迁移指南

移除 BinaryFormatter 后,预期许多 Windows Forms 应用程序将受到影响,你需要采取行动来完成到 .NET 9 或更高版本的迁移。

BinaryFormatter 影响 Windows Forms 的方式

在 .NET 9 之前,Windows Forms 使用 BinaryFormatter 在设计时会将数据序列化和反序列化,例如在剪贴板、拖放,以及存储或加载资源的情况下。 从 .NET 9 开始,Windows Forms 和 WPF 在这些情况中会在内部使用 BinaryFormatter 实现的一个子集。 虽然无法在通用序列化/反序列化中解决 BinaryFormatter 的风险,但我们已采取措施来在这些非常具体且已知类型的用例中缓解风险。 对于未知或不支持的类型,你仍可回退到 BinaryFormatter。除非在应用程序中执行了迁移步骤,否则这些类型将引发异常。

Windows Forms 和 WPF 应用都处理以下类型,以及这些类型的数组和列表。 剪贴板、拖放和设计时资源将继续使用这些类型,而无需执行任何迁移步骤。

Windows Forms 还支持以下其他类型:

OLE 方案

有关移除 BinaryFormatter 对剪贴板和拖放等 OLE 方案的影响方面的信息以及迁移指南,请参阅 Windows Forms 和 Windows Presentation Foundation BinaryFormatter OLE 指南

Resources (ResX)

Windows Forms 设计器

Windows Forms 进程外设计器还在内部对 ResX 序列化和反序列化使用 BinaryFormatter

由于 Windows Forms 设计器的标准行为,类型和属性可能会在不经过实现的情况下参与序列化。 你可能不知道的一种使用 BinaryFormatter 的方法是在 IComponent 上引入 public 属性并在设计时填充或编辑该属性。 在以下条件下,该属性被序列化为资源文件:

  • 系统在设计器中保存 Form 时,公共属性包含数据。
  • 该属性不是只读的。
  • 该属性未使用 [DesignerSerializationVisibility(false)] 来经特性化。
  • 该属性没有 DefaultValueAttribute
  • 该属性没有在 CodeDOM 序列化进行时返回 false 的相应 bool ShouldSerialize[PropertyName] 方法。 (注意:该方法可以有 private 范围。)
  • 这类属性没有 DesignerSerializer

如果这些语句为 true,设计器将确定该属性的类型是否具有类型转换器。 如果这样做,设计器会使用类型转换器将属性内容序列化。 否则,设计器会使用 BinaryFormatter 将内容序列化到资源文件中。 Windows Forms 添加了分析器以及代码修复,以帮助了解此类行为,即在开发人员没注意到的情况下,BinaryFormatter 可能会发生序列化。

在运行时加载资源

以前通过 BinaryFormatter 序列化为资源文件的类型将继续按预期进行反序列化,无需 BinaryFormatter,因为系统将 ResX 文件的内容视为受信任的数据。 在极少数情况下,没有 BinaryFormatter 时无法进行反序列化,此时可以通过不受支持的兼容性包将这些类型添加回去。 有关详细信息,请参阅 BinaryFormatter 迁移指南:兼容性包。 请注意,需要多执行一步,将 System.Resources.Extensions.UseBinaryFormatter 应用上下文切换设置为 true 才能将 BinaryFormatter 用于资源。

通过 msbuild 生成资源文件

通过 msbuild 生成资源文件时,可能会遇到一个 MSB3825 错误,该错误表明您的二进制格式的资源可能会在运行时使用 BinaryFormatter 进行反序列化。 如上所述,这些资源不会使用 BinaryFormatter 进行反序列化,并且可以通过将属性 GenerateResourceWarnOnBinaryFormatterUse 设置为 false 来关闭此警告。 在极少数情况下,没有 BinaryFormatter 时无法进行反序列化,此时可以通过不受支持的兼容性包将这些类型添加回去。 有关详细信息,请参阅 BinaryFormatter 迁移指南:兼容性包。 请注意,需要额外执行一步,将 System.Resources.Extensions.UseBinaryFormatter 应用上下文切换设置为 true 才能将 BinaryFormatter 用于资源。

从 BinaryFormatter 迁移

如果在受影响的情况中使用在序列化和反序列化期间未按固有方式处理的类型,则需要采取措施完成向 .NET 9 或更高版本的迁移。

OLE 方案

有关如何在剪贴板和拖放等情况中从 BinaryFormatter 迁移的详细信息,请参阅 Windows Forms 和 Windows Presentation Foundation BinaryFormatter OLE 指南

在设计时加载和保存资源

对于在序列化到资源期间未以固有方式处理的类型(例如对于使用 ResX 情况的设计器),从 BinaryFormatter 迁移的指定方法是确保为参与序列化的类型或属性注册一个 TypeConverter。 这样,在序列化和反序列化期间,将使用 TypeConverter 代替曾经使用 BinaryFormatter 的情况。 有关实施类型转换器的详细信息,请参阅 TypeConverter

无法从 BinaryFormatter 迁移的 .NET 9 用户可以安装不受支持的兼容性包。 有关详细信息,请参阅 BinaryFormatter 迁移指南:兼容性包

注意

BinaryFormatter 很危险,不推荐使用,因为它会使消耗的应用面临拒绝服务 (DoS)、信息泄露或远程代码执行等攻击的风险。 有关 BinaryFormatter 带来的风险的详细信息,请参阅使用 BinaryFormatter 和相关类型的反序列化风险

问题

如果 Windows Forms 应用遇到有关 BinaryFormatter 序列化或反序列化的意外行为,请在 github.com/dotnet/winforms 提交问题,并指明此问题与删除 BinaryFormatter 相关。