通过


迁移到 .NET Framework 4.6.x 的重定向更改

本文列出了 .NET Framework 4.64.6.14.6.2 中引入的应用兼容性问题。

.NET Framework 4.6

ASP.NET

HtmlTextWriter 未正确呈现 <br/> 元素

详细信息

从 .NET Framework 4.6 开始,调用 RenderBeginTag(String)RenderEndTag() 时,带有 <BR /> 元素的调用将正确插入一个 <BR />(而不是两个)

建议

如果应用依赖于多余的 <BR /> 标记,应再次调用 RenderBeginTag(String)。 请注意,此行为更改仅影响面向 .NET Framework 4.6 或更高版本的应用,因此另一选项是面向以前版本的 .NET Framework 以便获取旧行为。

名称
Scope Edge
版本 4.6
类型 重定目标

受影响的 API

ClickOnce

通过 ClickOnce 使用 SHA-256 代码签名证书发布的应用在 Windows 2003 中可能会失败

详细信息

使用 SHA256 对可执行文件签名。 以前,无论代码签名证书是 SHA-1 还是 SHA-256,都使用 SHA1 进行签名。 这适用于:

  • 使用 Visual Studio 2012 或更高版本生成的所有应用程序。
  • 使用 Visual Studio 2010 或更早版本在安装了 .NET Framework 4.5 的系统上生成的应用程序。 此外,如果安装了 .NET Framework 4.5 或更高版本,则 ClickOnce 清单也会采用 SHA-256 签名,因为 SHA-256 证书与编译所采用的 .NET Framework 版本无关。

建议

更改 ClickOnce 可执行文件的签名仅影响 Windows Server 2003 系统;它们需要安装 KB 938397。 即使应用程序面向 .NET Framework 4.0 或更早版本,对清单使用 SHA-256 签名的更改会引入对 .NET Framework 4.5 或更高版本的运行时依赖。

名称
Scope Edge
版本 4.5
类型 重定目标

ClickOnce 支持在面向 4.0 的应用程序中使用 SHA-256

详细信息

以前,如果 ClickOnce 应用具有使用 SHA-256 签名的证书,即使应用目标为 4.0 版本,也需要 .NET Framework 4.5 或更高版本。 现在,即使使用 SHA-256 签名,面向 .NET Framework 4.0 的 ClickOnce 应用也可在 .NET Framework 4.0 上运行。

建议

此更改删除了该依赖项,允许将 SHA-256 证书用于为面向 .NET Framework 4 或更早版本的 ClickOnce 应用签名。

名称
Scope 次要
版本 4.6
类型 重定目标

核心

CurrentCulture 和 CurrentUICulture 在任务之间流动

详细信息

从 .NET Framework 4.6 开始,System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 存储在线程的 System.Threading.ExecutionContext 中,可跨异步操作流动。这意味着对 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 的更改将反映在稍后以异步方式运行的任务中。 这与旧版 .NET Framework 的行为不同(旧版会在所有异步任务中重置 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture)。

建议

受此更改影响的应用可通过将所需的 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 显式设置为异步任务中的首个操作来暂时解决此问题。 或者,可通过设置以下兼容性开关选择使用旧行为(不流动 System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture):

AppContext.SetSwitch("Switch.System.Globalization.NoAsyncCurrentCulture", true);

.NET Framework 4.6.2 中的 WPF 已修复此问题。 .NET Frameworks 4.6、4.6.1 中也通过 KB 3139549 修复了此问题。 面向 .NET Framework 4.6 或更高版本的应用程序将自动在 WPF 应用程序中获取正确行为 - System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture 将在调度程序操作中保留。

名称
Scope 次要
版本 4.6
类型 重定目标

受影响的 API

ETW 事件名称无法仅通过“Start”或“Stop”后缀区别开来

详细信息

在 .NET Framework 4.6 和 4.6.1 中,当两个 Windows 事件跟踪 (ETW) 事件名称仅因“Start”或“Stop”后缀不同(例如,当一个事件命名为 ArgumentException,另一个事件命名为 LogUserStart)时,运行时会抛出 LogUser。 在这种情况下,运行时不会构建不能发出任何日志记录的事件源。

建议

若要避免此异常,请确保两个事件名称不是只有“Start”或“Stop”后缀不同。从 .NET Framework 4.6.2 开始,将删除此要求,运行时可区分只有“Start”和“Stop”后缀不同的事件名称。

名称
Scope Edge
版本 4.6
类型 重定目标

实体框架

使用 Visual Studio 2013 构建 Entity Framework edmx 时,如果使用 EntityDeploySplit 或 EntityClean 任务,可能会失败,并出现错误 MSB4062。

详细信息

MSBuild 12.0 工具(包括在 Visual Studio 2013 中)更改了 MSBuild 文件位置,使得旧 Entity Framework 目标文件变为无效文件。 结果是 EntityDeploySplitEntityClean 任务失败,因为它们无法找到 Microsoft.Data.Entity.Build.Tasks.dll。 请注意,此中断是由于工具集 (MSBuild/VS) 更改而引起的,并不是因为 .NET Framework 更改。 它仅在升级开发人员工具时才会发生,仅升级 .NET Framework 不会发生。

建议

从 .NET Framework 4.6 开始,Entity Framework 目标文件已修复,可与新 MSBuild 布局一起使用。 升级到该版本的 Framework 将解决此问题。 或者,可使用此解决方法直接修补目标文件。

名称
Scope 主要
版本 4.5.1
类型 重定目标

JIT

在 try 区域中不允许使用 IL ret

详细信息

与 JIT64 实时编译器不同,RyuJIT(在 .NET Framework 4.6 中使用)不允许在试用区域中使用 IL ret 指令。 ECMA-335 规范不允许从试用区域返回,并且没有已知的托管编译器会生成此类 IL。 但是,如果通过反射发射生成,JIT64 编译器将执行此类 IL。

建议

如果应用正在生成在 try 区域中包含 ret 操作码的 IL,则该应用可能会面向 .NET Framework 4.5,以便使用旧的 JIT 并避免此中断。 或者,生成的 IL 可更新为在试用区域之后返回。

名称
Scope Edge
版本 4.6
类型 重定目标

.NET Framework 4.6 中新的 64 位 JIT 编译器

详细信息

从 .NET Framework 4.6 开始,新的 64 位 JIT 编译器用于实时编译。 在某些情况下,应用在使用 32 位编译器或较旧的 64 位 JIT 编译器运行时,会抛出意料之外的异常或观察到不同的表现。 此更改不影响 32 位 JIT 编译器。 已知差异如下:

  • 在某些情况下,在发布版本中启用优化时,拆箱操作可能会引发 NullReferenceException
  • 在某些情况下,在大型方法主体中执行生产代码可能会引发 StackOverflowException
  • 在某些情况下,传递给方法的结构将视为引用类型,而不是发布版本中的值类型。 此问题的表现形式之一是,集合中各个项的显示顺序出现异常。
  • 在某些情况下,如果启用了优化,无法正确比较 UInt16 值与其高位集。
  • 在某些情况下,尤其是在初始化数组值时,通过 OpCodes.Initblk IL 指令执行的内存初始化可能会使用不正确的值初始化内存。 这可能会导致异常未处理或输出不正确。
  • 在某些极少数情况下,如果启用了编译器优化,条件位测试可能会返回错误的 Boolean 值或引发异常。
  • 在某些情况下,如果 if 语句用于在进入 try 块之前和从 try 块中退出之前测试条件,且在 catchfinally 块中计算的条件相同,那么新版 64 位实时编译器会在优化代码时从 ifcatch 块中删除 finally 条件。 因此,ifcatch 块中的 finally 语句代码会无条件地执行。

建议

已知问题的缓解措施
如果遇到上面列出的问题,可以通过执行下列任一操作来解决:

  • 升级到 .NET Framework 4.6.2。 .NET Framework 4.6.2 随附的新版 64 位编译器解决了上面列出的所有已知问题。

  • 运行 Windows 更新,以确保 Windows 是最新版本。 .NET Framework 4.6 和 4.6.1 的服务更新解决除了取消装箱操作中的 NullReferenceException 以外的以上问题。

  • 使用旧版 64 位 JIT 编译器进行编译。 请参阅其他问题的缓解措施部分,详细了解如何执行此操作。 其他问题的缓解措施
    如果遇到的是旧版和新版 64 位 JIT 编译器编译的代码的其他任何行为差异,或是使用新版 64 位 JIT 编译器编译的应用程序的调试和发布版本的其他任何行为差异,可以使用旧版 64 位 JIT 编译器编译应用程序,具体操作如下:

  • 对于每个应用程序,可将 < 元素添加到应用程序配置文件中。 下面的代码禁用新版 64 位 JIT 编译器,改用旧版 64 位 JIT 编译器进行编译。

    <?xml version ="1.0"?>
    <configuration>
      <runtime>
       <useLegacyJit enabled="1" />
      </runtime>
    </configuration>
    
  • 对于每个用户,可以将名为 REG_DWORDuseLegacyJit 值添加到注册表的 HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework 密钥中。 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。

  • 对于每台计算机,可以将名为 REG_DWORDuseLegacyJit 值添加到注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework 密钥中。 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。 还可以在 Microsoft Connect 上报告 bug,告诉我们你遇到的问题。

名称
Scope Edge
版本 4.6
类型 重定目标

网络

证书 EKU OID 验证

详细信息

从 .NET Framework 4.6 开始,SslStreamServicePointManager 类执行增强型密钥使用 (EKU) 对象标识符 (OID) 验证。 增强型密钥使用 (EKU) 扩展是指示使用密钥的应用程序的对象标识符 (OID) 的集合。 EKU OID 验证过程使用远程证书回调来确保远程证书中包含适合预期用途的正确 OID。

建议

如果此更改不理想,您可以通过将以下开关添加到您应用配置文件的 <AppContextSwitchOverrides> 中来禁用证书 EKU OID 验证:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.Net.DontCheckCertificateEKUs=true" />
</runtime>

重要

此设置仅用于后向兼容性。 否则不建议使用它。

名称
Scope 次要
版本 4.6
类型 重定目标

受影响的 API

System.Net.ServicePointManager 和 System.Net.Security.SslStream 中仅支持 Tls 1.0、1.1 和 1.2 协议

详细信息

从 .NET Framework 4.6 开始, ServicePointManager 只允许类 SslStream 使用以下三种协议之一:Tls1.0、Tls1.1 或 Tls1.2。 不支持 SSL3.0 协议和 RC4 密码。

建议

建议的缓解操作是将服务器端应用升级到 Tls1.0、Tls1.1 或 Tls1.2。 如果这不可行或者如果客户端应用被中断,则可以使用 System.AppContext 类并采用如两种方式中的一种来选择退出此功能:

<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=true"/>
名称
Scope 次要
版本 4.6
类型 重定目标

受影响的 API

默认情况下,TLS 1.x 将 SCH_SEND_AUX_RECORD 标记传递给基础 SCHANNEL API

详细信息

使用 TLS 1.x 时,.NET Framework 依赖于基础 Windows SCHANNEL API。 从 .NET Framework 4.6 开始,SCH_SEND_AUX_RECORD 标记默认传递给 SCHANNEL。 这会导致 SCHANNEL 将要加密的数据拆分为两个单独的记录,第一个为单字节,第二个为 n-1 个字节。 在极少数情况下,这会中断客户端与假定数据驻留在单个记录中的现有服务器之间的通信。

建议

如果此更改中断了与现有服务器的通信,可以通过在应用配置文件的 <runtime> 部分中的 <AppContextSwitchOverrides> 元素中添加以下开关,禁用发送 SCH_SEND_AUX_RECORD 标志,并恢复之前不将数据拆分为单独记录的行为。

<runtime>
  <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchSendAuxRecord=true" />
</runtime>

重要

此设置仅用于后向兼容性。 否则不建议使用它。

名称
Scope Edge
版本 4.6
类型 重定目标

受影响的 API

Windows Communication Foundation (WCF)

调用具有 null 参数的 CreateDefaultAuthorizationContext 的方式已更改

详细信息

调用带有 null authorizationPolicies 参数的 System.IdentityModel.Policy.AuthorizationContext.CreateDefaultAuthorizationContext(IList<IAuthorizationPolicy>) 所返回的 System.IdentityModel.Policy.AuthorizationContext 的实现,在 .NET Framework 4.6 中发生了变化。

建议

在极少数情况下,使用自定义身份验证的 WCF 应用可能会看到行为差异。 在这类情况下,可使用以下两种方式之一还原以前的行为:

  • 重新编译你的应用以面向早于 4.6 的 .NET Framework 版本。 对于在 IIS 上托管的服务,请使用 <httpRuntime targetFramework="x.x"> 元素以用于早期版本的 .NET Framework。

  • 将下面的行添加到 app.config 文件的 <appSettings> 部分:

    <add key="appContext.SetSwitch:Switch.System.IdentityModel.EnableCachedEmptyDefaultAuthorizationContext" value="true" />
    
名称
Scope 次要
版本 4.6
类型 重定目标

受影响的 API

Windows 窗体

Icon.ToBitmap 成功将带 PNG 帧的图标转换为位图对象

详细信息

从面向 .NET Framework 4.6 的应用开始,Icon.ToBitmap 方法成功将带 PNG 帧的图标转换为 Bitmap 对象。

在面向 .NET Framework 4.5.2 和更低版本的应用中,如果 Icon 对象具有 PNG 帧,Icon.ToBitmap 方法将引发 ArgumentOutOfRangeException 异常。

此更改会影响以下应用:重新编译为面向 .NET Framework 4.6 的应用,以及对在 Icon 对象具有 PNG 帧时引发的 ArgumentOutOfRangeException 实施特殊处理的应用。 在.NET Framework 4.6 下运行时,转换成功,不再引发 ArgumentOutOfRangeException ,因此不再调用异常处理程序。

建议

如果不需要此行为,可以在 app.config 文件的 <runtime> 部分中添加下面的元素,从而保留旧行为:

<AppContextSwitchOverrides
value="Switch.System.Drawing.DontSupportPngFramesInIcons=true" />

如果 app.config 文件中已包含 AppContextSwitchOverrides 元素,则新值应与值特性合并,如下所示:

<AppContextSwitchOverrides
value="Switch.System.Drawing.DontSupportPngFramesInIcons=true;<previous key>=<previous value>" />
名称
Scope 次要
版本 4.6
类型 重定目标

受影响的 API

Windows Presentation Foundation (WPF)

在 WPF 分派器操作期间,CurrentCulture 不会被保留。

详细信息

从 .NET Framework 4.6 开始,在 System.Globalization.CultureInfo.CurrentCulture 中对 System.Globalization.CultureInfo.CurrentUICultureSystem.Windows.Threading.Dispatcher 的更改将会在该调度程序操作结束时丢失。 同样,在调度程序操作外对 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 的更改在执行该操作时可能不会反映出来。实际上,这意味着 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 更改可能不会在 WPF UI 回调和 WPF 应用程序中的其他代码之间流动。这是因为,从面向 .NET Framework 4.6 的应用开始,System.Threading.ExecutionContext 中的一项更改使 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 存储在执行上下文中。 WPF 调度程序操作存储用于启动操作的执行上下文,并在操作完成时还原以前的上下文。 由于 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 现在属于该上下文,因此,在调度程序操作中对它们所做的更改在操作之外不会保留。

建议

受此更改影响的应用可在字段中存储所需的 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture,并在所有调度程序操作正文(包括 UI 事件回调处理程序)中检查是否设置了正确的 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture。 或者,因为在此 WPF 更改之下的 ExecutionContext 更改仅影响面向 .NET Framework 4.6 或更高版本的应用,面向 .NET Framework 4.5.2 可避免出现此中断。面向 .NET Framework 4.6 或更高版本的应用也可以通过设置以下兼容性开关解决此问题:

AppContext.SetSwitch("Switch.System.Globalization.NoAsyncCurrentCulture", true);

.NET Framework 4.6.2 中的 WPF 已修复此问题。 .NET Frameworks 4.6、4.6.1 中也通过 KB 3139549 修复了此问题。 面向 .NET Framework 4.6 或更高版本的应用程序将自动在 WPF 应用程序中获取正确行为 - System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture 将在调度程序操作中保留。

名称
Scope 次要
版本 4.6
类型 重定目标

WPF 布局的边距舍入已更改

详细信息

边距舍入的方式以及边框和边框内的背景已更改。 此更改的结果是:

  • 元素的宽度或高度最多可以扩大或收缩一个像素。
  • 对象的位置最多可以移动一个像素。
  • 居中的元素最多可以垂直或水平地偏离中心一个像素。 默认情况下,仅对面向 .NET Framework 4.6 的应用启用此新布局。

建议

由于此修改通常可以消除高 DPI 下 WPF 控件右侧或底部的裁剪问题,因此那些面向早期版本的 .NET Framework 并且在 .NET Framework 4.6 上运行的应用程序,可以通过在 app.config 文件的 <runtime> 部分添加以下行来选择启用此新行为:

<AppContextSwitchOverrides value="Switch.MS.Internal.DoNotApplyLayoutRoundingToMarginsAndBorderThickness=false" />

面向 .NET Framework 4.6 但希望 WPF 控件使用之前的布局算法来呈现的应用可以通过将下面的行添加到 app.config 文件的 <runtime> 部分来执行此操作:

<AppContextSwitchOverrides value="Switch.MS.Internal.DoNotApplyLayoutRoundingToMarginsAndBorderThickness=true" />
名称
Scope 次要
版本 4.6
类型 重定目标

XML、XSLT

XmlWriter 当遇到无效的代理对时抛出异常

详细信息

对于面向 .NET Framework 4.5.2 或更早版本的应用程序,使用异常回退机制来编写无效的代理对并不会总是引发异常。 对于面向 .NET Framework 4.6 的应用,尝试写入无效的代理对会引发 System.ArgumentException

建议

如有必要,可通过设定为 .NET Framework 4.5.2 或更早版本来避免此中断。 或者,可在编写无效的代理项对前将其预处理为有效的 XML。

名称
Scope Edge
版本 4.6
类型 重定目标

受影响的 API

如果使用复合密钥并且一个密钥为空,XSD 架构验证现在可正确检测是否违反唯一约束

详细信息

在版本 4.6 之前的 .NET Framework 版本中存在一个 bug,即如果其中一个密钥为空,XSD 验证无法检测复合密钥上的唯一约束。 在 .NET Framework 4.6 中,此问题已得到更正。 这将导致更多准确的验证,但也可能导致某些 XML 无法被验证,而以前是可以的。

建议

如果需要更宽松的 .NET Framework 4.0 验证要求,可以选择让该验证应用程序针对 .NET Framework 4.5 或更早版本。 但在重定向到 .NET Framework 4.6 时,应执行代码评审,确保无需验证重复的复合密钥(如在此问题的描述中所述)。

名称
Scope Edge
版本 4.6
类型 重定目标

.NET 框架 4.6.1

核心

ZipArchiveEntry 对象的 FullName 属性中的路径分隔符更改

详细信息

对于面向 .NET Framework 4.6.1 及更高版本的应用,在通过重载 FullName 方法创建的 ZipArchiveEntry 对象的 CreateFromDirectory 属性中,路径分隔符已从反斜杠(“\”)改为了正斜杠(“/”)。 该更改使 .NET 实现遵循 .ZIP 文件格式规范的 4.4.17.1 部分,还允许 .ZIP 存档在非 Windows 系统上进行解压缩。
对于面向非 Windows 操作系统(如 Macintosh)上旧版 .NET Framework 的应用程序,解压缩其创建的 zip 文件将无法保留目录结构。 例如,在 Macintosh 上,该应用会创建一组文件,它们的文件名与目录路径相连,还与任何反斜杠(“\”)字符和文件名相连。 因此,不会保留解压缩的文件的目录结构。

建议

此更改对由 .NET Framework System.IO 命名空间中的 API 在 Windows 操作系统上解压缩的 .ZIP 文件的影响应该很小,因为这些 API 可以无缝处理作为路径分隔符的正斜杠(“/”)或反斜杠(“\”)。
如果不需要此更改,可在应用程序配置文件的 <runtime> 部分中添加配置设置,从而选择弃用此更改。 以下示例显示 <runtime> 部分和 Switch.System.IO.Compression.ZipFile.UseBackslash 选择退出开关:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IO.Compression.ZipFile.UseBackslash=true" />
</runtime>

此外,对于面向先前版本的 .NET Framework,但在 .NET Framework 4.6.1 及更高版本上运行的应用,可通过将配置设置添加到应用程序配置文件的 <runtime> 部分来选择启用此行为。 以下展示了 <runtime> 部分和 Switch.System.IO.Compression.ZipFile.UseBackslash 选择加入开关。

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IO.Compression.ZipFile.UseBackslash=false" />
</runtime>
名称
Scope Edge
版本 4.6.1
类型 重定目标

受影响的 API

Windows Communication Foundation (WCF)

与 TransportWithMessageCredential 安全模式绑定的 WCF

详细信息

从 .NET Framework 4.6.1 开始,可将使用 TransportWithMessageCredential 安全模式的 WCF 绑定设置为接收带有非对称安全密钥的未签名“to”标头的消息。默认情况下,.NET Framework 4.6.1 中将继续拒绝未签名“to”标头。 仅当应用程序使用 Switch.System.ServiceModel.AllowUnsignedToHeader 配置开关选择启用此新操作模式时,才会接受它们。

建议

由于这是一项可以选择使用的功能,因此它不应影响现有应用的行为。
要控制是否使用新行为,请使用以下配置设置:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.ServiceModel.AllowUnsignedToHeader=true" />
</runtime>
名称
Scope 透明
版本 4.6.1
类型 重定目标

受影响的 API

X509CertificateClaimSet.FindClaims 考虑到所有的“claimTypes”

详细信息

在面向 .NET Framework 4.6.1 的应用中,如果从 SAN 字段拥有多个 DNS 条目的证书初始化 X509 声明集,System.IdentityModel.Claims.X509CertificateClaimSet.FindClaims(String, String) 方法会尝试将 claimType 自变量与所有 DNS 条目进行匹配。对于面向以前版本的 .NET Framework 的应用,System.IdentityModel.Claims.X509CertificateClaimSet.FindClaims(String, String) 方法会尝试仅将 claimType 自变量与最后一个 DNS 条目进行匹配。

建议

此更改仅影响面向 .NET Framework 4.6.1 的应用程序。 在 DisableMultipleDNSEntries 兼容性开关中,此更改可能被禁用(在目标版本是4.6.1之前时可能被启用)。

名称
Scope 次要
版本 4.6.1
类型 重定目标

受影响的 API

Windows 窗体

Application.FilterMessage 不再对 IMessageFilter.PreFilterMessage 的可重入实现抛出异常

详细信息

在 .NET Framework 4.6.1 之前,当调用 FilterMessage(Message) 的过程中,如果调用了 PreFilterMessage(Message),而 PreFilterMessage(Message) 又调用了 System.Windows.Forms.Application.AddMessageFilter(IMessageFilter)System.Windows.Forms.Application.RemoveMessageFilter(IMessageFilter)(同时还调用了 DoEvents()),可能导致 System.IndexOutOfRangeException

从面向 .NET Framework 4.6.1 的应用程序开始,不再引发此异常,并且可能使用上述的可重入筛选器。

建议

请注意,FilterMessage(Message) 在上述描述的可重入 PreFilterMessage(Message) 行为中将不再抛出异常。 此更改仅影响面向 .NET Framework 4.6.1 的应用程序。面向 .NET Framework 4.6.1 的应用可使用 DontSupportReentrantFilterMessage 兼容性开关,选择退出此更改(或者面向较早的 Framework 的应用可选择使用此更改)。

名称
Scope Edge
版本 4.6.1
类型 重定目标

受影响的 API

Windows Presentation Foundation (WPF)

在支持触摸功能的系统上调用 System.Windows.Input.PenContext.Disable 时,可能会抛出 ArgumentException。

详细信息

在某些情况下,在启用触摸功能的系统上调用内部 System.Windows.Input.PenContext.Disable 方法可能会由于重入而引发未处理的T:System.ArgumentException

建议

此问题已在 .NET Framework 4.7 中得到解决。 若要避免此异常,升级到 .NET Framework 4.7 及以上版本。

名称
Scope Edge
版本 4.6.1
类型 重定目标

.NET Framework 4.6.2

ASP.NET

HttpRuntime.AppDomainAppPath 抛出 NullReferenceException

详细信息

在 .NET Framework 4.6.2 中,当检索包含空字符的 T:System.NullReferenceException 值时,运行时会引发 P:System.Web.HttpRuntime.AppDomainAppPath。在 .NET Framework 4.6.1 及早期版本中,运行时将引发 T:System.ArgumentNullException

建议

可执行以下任一操作来应对此更改:

  • 如果应用程序是在 .NET Framework 4.6.2 上运行,请处理 T:System.NullReferenceException
  • 升级到 .NET Framework 4.7,这将还原以前的行为并引发 T:System.ArgumentNullException
名称
Scope Edge
版本 4.6.2
类型 重定目标

受影响的 API

核心

AesCryptoServiceProvider 解密器提供了可重用的转换

详细信息

从面向 .NET Framework 4.6.2 的应用起,AesCryptoServiceProvider 解密器提供了可重用的转换。 调用 System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[], Int32, Int32) 后,此转换将重新初始化并且可以重用。 对于面向旧版 .NET Framework 的应用,在调用 System.Security.Cryptography.CryptoAPITransform.TransformBlock(Byte[], Int32, Int32, Byte[], Int32) 后尝试通过调用 System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[], Int32, Int32) 重用解密器会引发 CryptographicException 或导致数据损坏。

建议

此更改的影响应该很小,因为这是预期的行为。对于依赖旧行为的应用程序,可通过将以下配置设置添加到应用程序配置文件的 <runtime> 部分中,从而选择不用此更改:

<runtime>
<AppContextSwitchOverrides value="Switch.System.Security.Cryptography.AesCryptoServiceProvider.DontCorrectlyResetDecryptor=true"/>
</runtime>

此外,面向旧版本 .NET Framework 的应用程序,在 .NET Framework 4.6.2 及更高版本下运行时,可以通过在应用程序配置文件的 <runtime> 部分添加以下配置设置来选择启用该功能:

<runtime>
<AppContextSwitchOverrides value="Switch.System.Security.Cryptography.AesCryptoServiceProvider.DontCorrectlyResetDecryptor=false"/>
</runtime>
名称
Scope 次要
版本 4.6.2
类型 重定目标

受影响的 API

调用 ClaimsIdentity 构造函数

详细信息

从 .NET Framework 4.6.2 开始,具有 ClaimsIdentity 参数的 System.Security.Principal.IIdentity 构造函数设置 System.Security.Claims.ClaimsIdentity.Actor 属性的方式发生了变化。 如果 System.Security.Principal.IIdentity 参数是 ClaimsIdentity 对象,且该 System.Security.Claims.ClaimsIdentity.Actor 对象的 ClaimsIdentity 属性不为 null,则 System.Security.Claims.ClaimsIdentity.Actor 属性是使用 Clone() 方法附加的。 在 Framework 4.6.1 及早期版本中,System.Security.Claims.ClaimsIdentity.Actor 属性作为现有引用进行附加。由于此更改,从 .NET Framework 4.6.2 开始,新 System.Security.Claims.ClaimsIdentity.Actor 对象的 ClaimsIdentity 属性不等于构造函数的 System.Security.Claims.ClaimsIdentity.Actor 参数的 System.Security.Principal.IIdentity 属性。 在 .NET Framework 4.6.1 及更早版本中,它们是相等的。

建议

如果不需要此行为,可以在应用程序配置文件中将 Switch.System.Security.ClaimsIdentity.SetActorAsReferenceWhenCopyingClaimsIdentity 开关设置为 true,从而还原旧行为。 为此,必须在 web.config 文件的 <runtime> 部分中添加以下内容:

<configuration>
  <runtime>
    <AppContextSwitchOverrides value="Switch.System.Security.ClaimsIdentity.SetActorAsReferenceWhenCopyingClaimsIdentity=true" />
  </runtime>
</configuration>
名称
Scope Edge
版本 4.6.2
类型 重定目标

受影响的 API

路径规范化中的更改

详细信息

从面向 .NET Framework 4.6.2 的应用开始,运行时规范路径的方式发生了变化。路径规范化涉及修改用于标识路径或文件的字符串,使其与目标操作系统上的有效路径一致。 路径规范化通常涉及以下操作:

  • 规范化组件和目录分隔符。
  • 将当前目录应用到相对路径。
  • 评估路径中的相对目录 (.) 或父目录 (..)。
  • 删减指定字符。 从面向 .NET Framework 4.6.2 的应用开始,在路径规范化中默认启用以下更改:
    • 运行时环境将路径规范化处理委托给操作系统的 GetFullPathName 函数。
  • 路径规范化再也不用删减目录部分的末尾内容(如目录名称末尾的空格)。
  • 支持完全信任形式的设备路径语法,包括 \\.\\\?\(对于 mscorlib.dll 中的文件 I/O API)。
  • 运行时不会验证设备语法路径。
  • 支持使用设备语法来访问备用数据流。 这些更改会提升性能,同时允许方法访问之前无法访问的路径。 针对 .NET Framework 4.6.1 及更早版本的应用程序,但在 .NET Framework 4.6.2 或更高版本上运行,则不受此更改的影响。

建议

对于面向 .NET Framework 4.6.2 或更高版本的应用,可通过将以下内容添加到应用程序配置文件的 <runtime> 部分,选择弃用此更改而使用旧版规范化:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=true" />
</runtime>

对于面向 .NET Framework 4.6.1 及更低版本,但在 .NET Framework 4.6.2 或更高版本上运行的应用,可通过将以下行添加到应用程序配置文件的 <runtime> 部分,启用对路径规范化的更改:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
</runtime>
名称
Scope 次要
版本 4.6.2
类型 重定目标

CurrentCulture 和 CurrentUICulture 在任务之间流动

详细信息

从 .NET Framework 4.6 开始,System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 存储在线程的 System.Threading.ExecutionContext 中,可跨异步操作流动。这意味着对 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 的更改将反映在稍后以异步方式运行的任务中。 这与旧版 .NET Framework 的行为不同(旧版会在所有异步任务中重置 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture)。

建议

受此更改影响的应用可通过将所需的 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 显式设置为异步任务中的首个操作来暂时解决此问题。 或者,可以通过设置以下兼容性开关来选择启用旧行为(使System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture不流动):

AppContext.SetSwitch("Switch.System.Globalization.NoAsyncCurrentCulture", true);

.NET Framework 4.6.2 中的 WPF 已修复此问题。 .NET Frameworks 4.6、4.6.1 中也通过 KB 3139549 修复了此问题。 面向 .NET Framework 4.6 或更高版本的应用程序将自动在 WPF 应用程序中获取正确行为 - System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture 将在调度程序操作中保留。

名称
Scope 次要
版本 4.6
类型 重定目标

受影响的 API

ETW 事件名称无法仅通过“Start”或“Stop”后缀区别开来

详细信息

在 .NET Framework 4.6 和 4.6.1 中,当两个 Windows 事件跟踪 (ETW) 事件名称只有“Start”或“Stop”后缀不同时(例如,当一个事件命名为 LogUser,另一个事件命名为 LogUserStart),运行时会抛出 ArgumentException。 在这种情况下,运行时不会构建不能发出任何日志记录的事件源。

建议

若要避免此异常,请确保两个事件名称不是只有“Start”或“Stop”后缀不同。从 .NET Framework 4.6.2 开始,将删除此要求,运行时可区分只有“Start”和“Stop”后缀不同的事件名称。

名称
Scope Edge
版本 4.6
类型 重定目标

长路径支持

详细信息

从面向 .NET Framework 4.6.2 的应用开始,支持长路径(最多 32K 个字符),并删除了 260 个字符(或 MAX_PATH)的路径长度限制。对于经过重新编译以面向 .NET Framework 4.6.2 的应用,之前因路径超过 260 个字符而引发 System.IO.PathTooLongException 的代码路径,现在仅在以下情况下引发 System.IO.PathTooLongException

  • 路径长度必须大于 MaxValue (32,767) 个字符。
  • 操作系统返回 COR_E_PATHTOOLONG 或其等同项。 对于面向 .NET Framework 4.6.1 及更早版本的应用,只要路径超过 260 个字符,运行时就会自动引发 System.IO.PathTooLongException

建议

对于面向 .NET Framework 4.6.2 的应用,如果无需长路径支持,可通过将以下内容添加到 <runtime> 文件的 app.config 部分来选择弃用该支持:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IO.BlockLongPaths=true" />
</runtime>

对于面向旧版 .NET Framework,但在 .NET Framework 4.6.2 或更高版本上运行的应用,可通过将以下内容添加到 <runtime> 文件的 app.config 部分来选择启用长路径支持:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IO.BlockLongPaths=false" />
</runtime>
名称
Scope 次要
版本 4.6.2
类型 重定目标

路径冒号检查更严格

详细信息

在 .NET Framework 4.6.2 中,为了支持以前不受支持的路径,进行了大量更改(无论是在长度方面还是在格式方面)。 检查正确的驱动器分隔符(冒号)语法变得更加严格,这样做的副作用是阻止了少量特选路径 API 中的某些 URI 路径,而这些之前已被容忍的。

建议

如果将 URI 传递给受影响的 API,请首先将该字符串修改为合法路径。

  • 手动从 URL 中删除该方案(例如从 URL 中删除 file://)。

  • 将 URI 传递给 Uri 类并使用 LocalPath

或者,通过将 Switch.System.IO.UseLegacyPathHandling AppContext 开关设置为 true 来选择不用新路径规范化。

名称
Scope Edge
版本 4.6.2
类型 重定目标

受影响的 API

安全性

RSACng 现在可正确加载非标准密钥大小的 RSA 密钥

详细信息

在 .NET Framework 4.6.2 之前的版本中,使用非标准密钥大小的 RSA 证书的客户无法通过 System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPublicKey(X509Certificate2)System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2) 扩展方法访问这些密钥。 被抛出 System.Security.Cryptography.CryptographicException,并显示消息“所请求的密钥大小不受支持”。 .NET Framework 4.6.2 中已修复此问题。 同样,ImportParameters(RSAParameters)ImportParameters(RSAParameters) 现在可以处理非标准密钥大小,而不会引发 System.Security.Cryptography.CryptographicException

建议

如果某些异常处理逻辑依赖于先前的行为,即在使用非标准密钥大小时会引发System.Security.Cryptography.CryptographicException,请考虑删除这些逻辑。

名称
Scope Edge
版本 4.6.2
类型 重定目标

受影响的 API

SignedXml.GetPublicKey 在 net462 或 lightup 上返回 RSACng,而无需进行重定向更改。

详细信息

从 .NET Framework 4.6.2 开始,SignedXml.GetPublicKey 方法所返回对象的具体类型从 CryptoServiceProvider 实现更改为 Cng 实现(不奇怪)。 这是因为实现已从使用 certificate.PublicKey.Key 更改为使用内部 certificate.GetAnyPublicKey(将转到 RSACertificateExtensions.GetRSAPublicKey)。

建议

从在 .NET Framework 4.7.1 上运行的应用开始,可通过将以下配置开关添加到应用配置文件的运行时部分,使用 .NET Framework 4.6.1 和早期版本中默认使用的 CryptoServiceProvider 实现:

<AppContextSwitchOverrides value="Switch.System.Security.Cryptography.Xml.SignedXmlUseLegacyCertificatePrivateKey=true" />
名称
Scope Edge
版本 4.6.2
类型 重定目标

受影响的 API

Windows Communication Foundation (WCF)

使用可重入服务时可能导致死锁

详细信息

死锁可能导致重入服务将服务实例每次只能由一个执行线程处理。 代码中包含以下 ServiceBehaviorAttribute 的服务容易遇到此问题:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]

建议

要解决此问题,可执行以下操作:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
  • 安装 .NET Framework 4.6.2 的最新更新,或升级到更高版本的 .NET Framework。 这将在 ExecutionContext 中禁用 OperationContext.Current 的流。 此行为是可配置的;它相当于将以下应用设置添加到配置文件中:
<appSettings>
  <add key="Switch.System.ServiceModel.DisableOperationContextAsyncFlow" value="true" />
</appSettings>

对于 Reentrant 服务,Switch.System.ServiceModel.DisableOperationContextAsyncFlow 的值绝不能设置为 false

名称
Scope 次要
版本 4.6.2
类型 重定目标

受影响的 API

OperationContext.Current 在 using 子句中被调用时可能返回 null

详细信息

如果满足以下所有条件,那么 OperationContext.Current 可能返回 null 且导致 NullReferenceException

using (new OperationContextScope(OperationContext.Current))
{
    // OperationContext.Current is null.
    OperationContext context = OperationContext.Current;

    // ...
}

建议

要解决此问题,可执行以下操作:

  • 按如下所示修改代码,实例化一个新的非 nullCurrent 对象:

    OperationContext ocx = OperationContext.Current;
    using (new OperationContextScope(OperationContext.Current))
    {
        OperationContext.Current = new OperationContext(ocx.Channel);
    
        // ...
    }
    
  • 安装 .NET Framework 4.6.2 的最新更新,或升级到更高版本的 .NET Framework。 这将禁用 ExecutionContext 中的 OperationContext.Current 流并还原 .NET Framework 4.6.1 以及更低版本中的 WCF 应用程序行为。 此行为是可配置的;它相当于将以下应用设置添加到配置文件中:

    <appSettings>
      <add key="Switch.System.ServiceModel.DisableOperationContextAsyncFlow" value="true" />
    </appSettings>
    

    如果不需要此更改并且应用程序依赖操作上下文间的执行上下文流,那么可以启用它的流,如下所示:

    <appSettings>
      <add key="Switch.System.ServiceModel.DisableOperationContextAsyncFlow" value="false" />
    </appSettings>
    
名称
Scope Edge
版本 4.6.2
类型 重定目标

受影响的 API

WCF 传输安全性支持使用 CNG 存储的证书

详细信息

从面向 .NET Framework 4.6.2 的应用起,WCF 传输安全性支持使用 Windows 加密库 (CNG) 存储的证书。 此兼容性仅限于使用指数长度不超过 32 位的公钥的证书。 当应用程序面向 .NET Framework 4.6.2 时,此功能默认启用。在旧版 .NET framework 中,尝试将 X509 证书与 CSG 密钥存储提供程序结合使用会引发异常。

建议

应用如果面向 .NET Framework 4.6.1 和更早版本,但在 .NET Framework 4.6.2 上运行,则可通过将以下行添加到 app.config 或 web.config 文件的 <runtime> 部分来启用对 CNG 证书的支持:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IdentityModel.DisableCngCertificates=false" />
</runtime>

也可以使用以下代码以编程方式完成此操作:

private const string DisableCngCertificates = @"Switch.System.IdentityModel.DisableCngCertificate";

AppContext.SetSwitch(disableCngCertificates, false);
Const DisableCngCertificates As String = "Switch.System.IdentityModel.DisableCngCertificates"
AppContext.SetSwitch(disableCngCertificates, False)

请注意,由于此更改,依赖尝试使用 CNG 证书启动安全通信失败的异常处理代码将不再执行。

名称
Scope 次要
版本 4.6.2
类型 重定目标

Windows 窗体

MemberDescriptor.Equals 实现不正确

详细信息

MemberDescriptor.Equals 方法的原始实现比较两个被比较对象中的不同字符串属性:类别名称和描述字符串。 解决方法是比较第一个对象的 Category 和第二个对象的 Category,并比较第一个对象的 Description 和第二个对象的 Description

建议

如果您的应用程序依赖于在描述符相等时 false 有时返回 MemberDescriptor.Equals,并且目标是 .NET Framework 4.6.2 或更高版本,那么您有以下几个选项:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.MemberDescriptorEqualsReturnsFalseIfEquivalent=true" />
</runtime>

如果应用程序面向 .NET Framework 4.6.1 或更低版本,并且在 .NET Framework 4.6.2 及更高版本上运行且你想要启用此更改,可以通过将以下值添加到 app.config 文件以将兼容性开关设为 false

<runtime>
  <AppContextSwitchOverrides value="Switch.System.MemberDescriptorEqualsReturnsFalseIfEquivalent=false" />
</runtime>
名称
Scope Edge
版本 4.6.2
类型 重定目标

受影响的 API

Windows Presentation Foundation (WPF)

在 WPF 分派器操作期间,CurrentCulture 不会被保留。

详细信息

从 .NET Framework 4.6 开始,在 System.Globalization.CultureInfo.CurrentCulture 中对 System.Globalization.CultureInfo.CurrentUICultureSystem.Windows.Threading.Dispatcher 的更改将会在该调度程序操作结束时丢失。 同样,在调度程序操作外对 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 的更改在执行该操作时可能不会反映出来。实际上,这意味着 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 更改可能不会在 WPF UI 回调和 WPF 应用程序中的其他代码之间流动。这是因为,从面向 .NET Framework 4.6 的应用开始,System.Threading.ExecutionContext 中的一项更改使 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 存储在执行上下文中。 WPF 调度程序操作存储用于启动操作的执行上下文,并在操作完成时还原以前的上下文。 由于 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture 现在属于该上下文,因此,在调度程序操作中对它们所做的更改在操作之外不会保留。

建议

受此更改影响的应用可在字段中存储所需的 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture,并在所有调度程序操作正文(包括 UI 事件回调处理程序)中检查是否设置了正确的 System.Globalization.CultureInfo.CurrentCultureSystem.Globalization.CultureInfo.CurrentUICulture。 或者,因为在此 WPF 更改之下的 ExecutionContext 更改仅影响面向 .NET Framework 4.6 或更高版本的应用,面向 .NET Framework 4.5.2 可避免出现此中断。面向 .NET Framework 4.6 或更高版本的应用也可以通过设置以下兼容性开关解决此问题:

AppContext.SetSwitch("Switch.System.Globalization.NoAsyncCurrentCulture", true);

.NET Framework 4.6.2 中的 WPF 已修复此问题。 .NET Frameworks 4.6、4.6.1 中也通过 KB 3139549 修复了此问题。 面向 .NET Framework 4.6 或更高版本的应用程序将自动在 WPF 应用程序中获取正确行为 - System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture 将在调度程序操作中保留。

名称
Scope 次要
版本 4.6
类型 重定目标