添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
温柔的红薯  ·  CAS Authentication :: ...·  1 月前    · 
叛逆的太阳  ·  react ...·  10 月前    · 
慈祥的佛珠  ·  PowerShell is open ...·  1 年前    · 

如果要从 .NET Framework 4.0 迁移到 4.8,请查看以下主题,了解可能影响你的应用的应用程序兼容性问题:

ADO.NET

DbParameter.Precision 和 DbParameter.Scale 现在是公共虚拟成员

实现 Precision Scale 将实现为公共虚拟属性。 它们替换相应的显示接口实现、 IDbDataParameter.Precision IDbDataParameter.Scale

在重新生成 ADO.NET 数据库提供程序时,这些差异要求将“override”关键字应用到 Precision 和 Scale 属性。 仅在重新生成组件时才需要这样做;现有二进制文件将继续运行。

.NET Framework 4.7.1 中的 ASP.NET 辅助功能改进

从 .NET Framework 4.7.1 开始,ASP.NET 改进了 ASP.NET Web 控件与 Visual Studio 中的辅助功能技术配合使用的方式,以更好地支持 ASP.NET 客户。 其中包括以下更改:

  • 在以下控件中实现缺失 UI 的辅助功能模式:例如“详细信息视图”向导中的“添加字段”对话框或“ListView”向导的“配置 ListView”对话框。
  • 改善在高对比度模式下(如数据页导航字段编辑器)的显示。
  • 更改用于改善以下控件的键盘导航体验:如 DataPager 控件的“编辑页导航字段”向导中的“字段”对话框、“配置 ObjectContext”对话框或“配置数据源”向导的“配置数据选择”对话框。
  • 如何选择启用或弃用这些更改 为使 Visual Studio 设计器从这些更改中获益,它必须在 .NET Framework 4.7.1 或更高版本上运行。 Web 应用程序可通过以下任何一种方式从这些更改中获益:

  • 安装 Visual Studio 2017 15.3 或更高版本,它在默认情况下使用以下 AppContext 开关支持新的辅助功能。
  • 如以下示例所示,通过将 Switch.UseLegacyAccessibilityFeatures AppContext 开关添加到 devenv.exe.config 文件中的 <runtime> 部分并将其设置为 false ,可选择弃用旧版辅助功能行为。
  • <?xml version="1.0" encoding="utf-8"?>
    <configuration>
    <runtime>
    <!-- AppContextSwitchOverrides value attribute is in the form of 'key1=true/false;key2=true/false'  -->
    <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false" />
    </runtime>
    </configuration>
    

    面向 .NET Framework 4.7.1 或更高版本并希望保留旧版辅助功能行为的应用程序,可通过将此 AppContext 开关显式设置为 true 来选择启用旧版辅助功能。

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

    从 .NET Framework 4.6 开始,调用带有 <BR />RenderBeginTag(String)RenderEndTag() 将正确插入唯一 <BR />(而非两个)

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

  • HtmlTextWriter.RenderBeginTag(HtmlTextWriterTag)
  • MachineKey.Encode 和 MachineKey.Decode 方法现已过时

    这些方法现在已过时。 调用这些方法的代码编译会产生编译器警告。

    建议的替代项为 Protect(Byte[], String[])Unprotect(Byte[], String[])。 或者,可以禁止显示生成警告,也可以使用较早的编译器避免出现此类警告。 API 仍受支持。

  • MachineKey.Encode(Byte[], MachineKeyProtection)
  • MachineKey.Decode(String, MachineKeyProtection)
  • 使用 AntiXSSEncoder 时,多行 ASP.NET 文本框间距已更改

    在 .NET Framework 4.0 中,如果使用 System.Web.Security.AntiXss.AntiXssEncoder,则多余行将插入回发的多行文本框中的各行之间。 在 .NET Framework 4.5 中,不包括这些多余的换行符,仅在 Web 应用面向 .NET Framework 4.5 时才可包含

    请注意,重定向到 .NET Framework 4.5 的 4.0 Web 应用可能改进了多行文本框,从而不再插入多余的换行符。 如果不需要这样做,当应用在 .NET Framework 4.5 上运行时,通过面向 .NET Framework 4.0 可使用旧行为。

    每个会话的限制并发请求数

    在 .NET Framework 4.6.2 和更早版本中,ASP.NET 使用相同的 Sessionid 依次执行请求,且 ASP.NET 始终默认通过 cookie 发出 Sessionid。 如果页面响应时间较长,只需在浏览器上按 F5 即可显著降低服务器性能。 在此修复程序中,我们添加了一个计数器来跟踪排队的请求,并在请求超过指定限制时终止请求。 默认值为 50。 如果达到限制,事件日志中会记录一条警告,并且 IIS 日志中可能会记录 HTTP 500 响应。

    若要还原旧行为,可以在 web.config 文件中添加下面的设置,从而选择禁用新行为。

    <appSettings>
        <add key="aspnet:RequestQueueLimitPerSession" value="2147483647"/>
    </appSettings>
    

    WebUtility.HtmlEncode 和 WebUtility.HtmlDecode 正确往返 BMP

    对于面向 .NET Framework 4.5 的应用程序,当基本多语言平面 (BMP) 外的字符传递给 HtmlDecode(String) 方法时,这些字符可正确往返。

    此更改不应影响当前应用程序,但要还原原始行为,请将 <httpRuntime> 元素的 targetFramework 属性设置为“4.5”以外的字符串。 还可以设置 unicodeEncodingConformance 配置元素的 unicodeDecodingConformance<webUtility> 特性以单独控制 .NET Framework 的目标版本的行为。

    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 应用签名。

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

    从面向 .NET Framework 4.6.2 的应用起,AesCryptoServiceProvider 解密器提供了可重用的转换。 调用 System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[], Int32, Int32) 后,此转换将重新初始化并且可以重用。 对于面向旧版 .NET Framework 的应用,在调用 System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[], Int32, Int32) 后尝试通过调用 System.Security.Cryptography.CryptoAPITransform.TransformBlock(Byte[], Int32, Int32, Byte[], 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>
    

    允许在 URI 中使用 Unicode 双向控制字符

    Unicode 指定数个特殊控制字符,用于指定文本方向。 在 .NET Framework 先前版本中,即使这些字符已经以百分比编码形式出现,但还是会被错误地从所有 URI 中去除。 为了更好地遵守 RFC 3987,现在,我们允许在 URI 中使用这些字符。 如果在 URI 中出现未编码的字符,则对其进行百分比编码。 如果出现百分比编码的字符,则原样保留。

    对于面向 .NET Framework 4.7.2 及更高版本的应用程序,默认启用对 Unicode 双向字符的支持。 如果不需要此更改,可通过将以下 AppContextSwitchOverrides 开关添加到应用程序配置文件的 <runtime> 部分,从而禁用更改:

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

    对于面向 .NET Framework 早期版本但在 .NET Framework 4.7.2 及更高版本下运行的应用程序,默认禁用对 Unicode 双向字符的支持。 可通过将以下 AppContextSwitchOverrides 开关添加到应用程序配置文件的 <runtime> 部分,进行启用:

    <runtime>
    <AppContextSwitchOverrides value="Switch.System.Uri.DontKeepUnicodeBidiFormattingCharacters=false" />
    </runtime>
    

    调用 ClaimsIdentity 构造函数

    从 .NET Framework 4.6.2 开始,具有 System.Security.Principal.IIdentity 参数的 ClaimsIdentity 构造函数设置 System.Security.Claims.ClaimsIdentity.Actor 属性的方式发生了变化。 如果 System.Security.Principal.IIdentity 参数是 ClaimsIdentity 对象,且该 ClaimsIdentity 对象的 System.Security.Claims.ClaimsIdentity.Actor 属性不为 null,则 System.Security.Claims.ClaimsIdentity.Actor 属性是使用 Clone() 方法附加的。 在 Framework 4.6.1 及早期版本中,System.Security.Claims.ClaimsIdentity.Actor 属性作为现有引用进行附加。由于此更改,从 .NET Framework 4.6.2 开始,新 ClaimsIdentity 对象的 System.Security.Claims.ClaimsIdentity.Actor 属性不等于构造函数的 System.Security.Principal.IIdentity 参数的 System.Security.Claims.ClaimsIdentity.Actor 属性。 在 .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>
    
  • ClaimsIdentity(IIdentity)
  • ClaimsIdentity(IIdentity, IEnumerable<Claim>)
  • ClaimsIdentity(IIdentity, IEnumerable<Claim>, String, String, String)
  • ZipArchiveEntry 对象的 FullName 属性中的路径分隔符更改

    对于面向 .NET Framework 4.6.1 及更高版本的应用,在通过重载 CreateFromDirectory 方法创建的 ZipArchiveEntry 对象的 FullName 属性中,路径分隔符已从反斜杠(“\”)改为了正斜杠(“/”)。 该更改使 .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>
    
  • ZipFile.CreateFromDirectory(String, String)
  • ZipFile.CreateFromDirectory(String, String, CompressionLevel, Boolean)
  • ZipFile.CreateFromDirectory(String, String, CompressionLevel, Boolean, Encoding)
  • 路径规范化中的更改

    从面向 .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>
      

      DeflateStream 使用本机 API 进行解压缩

      从 .NET Framework 4.7.2 开始,T:System.IO.Compression.DeflateStream 类中解压缩的实现已更改为默认使用本机 Windows API。 通常情况下,这能大大地提高性能。 所有面向 .NET Framework 4.7.2 或更高版本的 .NET 应用程序均使用本机实现。此更改可能会导致某些行为差异,其中包括:

    • 异常消息可能有所不同。 但是,引发的异常类型保持不变。
    • 可能以不同的方式处理某些特殊情况(例如没有足够的内存完成操作)。
    • 分析 gzip 标头存在一些已知差异(注意:仅影响用于解压缩的 GZipStream 集):
    • 分析无效标头时出现异常可能在不同的时间引发。
    • 本机实现强制根据规范设置 gzip 标头(即 FLG)内的一些保留标记值,这可能导致其在忽略先前无效值的情况下引发异常。
    • 如果借助本机 API 解压缩对应用行为产生负面影响,则可通过将 Switch.System.IO.Compression.DoNotUseNativeZipLibraryForDecompression 开关添加到 app.config 文件的 runtime 部分并将其设置为 true,选择弃用此功能:

      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
        <runtime>
          <AppContextSwitchOverrides value="Switch.System.IO.Compression.DoNotUseNativeZipLibraryForDecompression=true" />
        </runtime>
      </configuration>
      

      确保 System.Uri 使用一致的保留字符集

      System.Uri 中,某些有时会被解码的百分比编码字符现在始终保持编码状态。 这种情况发生在访问 URI 的路径、查询、片段或用户信息组件的属性和方法中。 仅当以下两项均为 true 时,该行为才会更改:

    • URI 包含以下任意保留字符的编码形式::'()!*
    • URI 包含 Unicode 或编码的非保留字符。 如果以上两项均为 true,则编码的保留字符保持编码状态。 在先前版本的 .NET Framework 中,它们为解码状态。
    • 对于面向 .NET Framework 4.7.2 及更高版本的应用程序,默认启用新的解码行为。 如果不需要此更改,可通过将以下 AppContextSwitchOverrides 开关添加到应用程序配置文件的 <runtime> 部分,从而禁用更改:

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

      对于面向 .NET Framework 早期版本,但在 .NET Framework 4.7.2 及更高版本下运行的应用程序,默认禁用新的解码行为。 可通过将以下 AppContextSwitchOverrides 开关添加到应用程序配置文件的 <runtime> 部分,进行启用:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Uri.DontEnableStrictRFC3986ReservedCharacterSets=false" />
      </runtime>
      

      Foreach 迭代器变量现在已在迭代范围内,因此闭包捕获语义会不同(在 C#5 中)

      从 C# 5 (Visual Studio 2012) 开始,foreach 迭代器变量在迭代范围内。 如果代码以前依靠变量而不在 foreach 闭包内,这可能会导致中断。 此更改的特征如下:传递到委托的迭代器变量将视为委托创建时它拥有的值,而非调用委托时它拥有的值。

      理想情况下,应更新代码以使用新的编译器行为。 如果需要旧语义,迭代器变量可替换为显式置于循环范围外的单独变量。

      IAsyncResult.CompletedSynchronously 属性必须正确,才能完成生成的任务

      在调用 TaskFactory.FromAsync 时,必须正确实现 CompletedSynchronously 属性,才能完成生成的任务。 即,当且仅当同步完成实现时,该属性才应返回 true。 之前,属性未被选中。

      如果仅在任务同步完成时,System.IAsyncResult 实现才为 System.IAsyncResult.CompletedSynchronously 属性正确返回 true,将观察不到任何中断。 用户应查看所拥有的 System.IAsyncResult 实现(如果有),确保能够正确评估某项任务是否同步完成。

    • TaskFactory.FromAsync(IAsyncResult, Action<IAsyncResult>)
    • TaskFactory.FromAsync(IAsyncResult, Action<IAsyncResult>, TaskCreationOptions)
    • TaskFactory.FromAsync(IAsyncResult, Action<IAsyncResult>, TaskCreationOptions, TaskScheduler)
    • TaskFactory.FromAsync<TResult>(IAsyncResult, Func<IAsyncResult,TResult>)
    • TaskFactory.FromAsync(Func<AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, Object)
    • TaskFactory.FromAsync(Func<AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, Object, TaskCreationOptions)
    • TaskFactory.FromAsync<TArg1>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, Object)
    • TaskFactory.FromAsync<TArg1>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, Object, TaskCreationOptions)
    • TaskFactory.FromAsync<TResult>(Func<AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, Object)
    • TaskFactory.FromAsync<TResult>(Func<AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, Object, TaskCreationOptions)
    • TaskFactory.FromAsync<TResult>(IAsyncResult, Func<IAsyncResult,TResult>, TaskCreationOptions)
    • TaskFactory.FromAsync<TResult>(IAsyncResult, Func<IAsyncResult,TResult>, TaskCreationOptions, TaskScheduler)
    • TaskFactory.FromAsync<TArg1,TArg2>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, Object)
    • TaskFactory.FromAsync<TArg1,TArg2>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, Object, TaskCreationOptions)
    • TaskFactory.FromAsync<TArg1,TResult>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, Object)
    • TaskFactory.FromAsync<TArg1,TResult>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, Object, TaskCreationOptions)
    • TaskFactory.FromAsync<TArg1,TArg2,TResult>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, Object)
    • TaskFactory.FromAsync<TArg1,TArg2,TArg3>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, TArg3, Object)
    • TaskFactory.FromAsync<TArg1,TArg2,TArg3>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, TArg3, Object, TaskCreationOptions)
    • TaskFactory.FromAsync<TArg1,TArg2,TResult>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, Object, TaskCreationOptions)
    • TaskFactory.FromAsync<TArg1,TArg2,TArg3,TResult>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, TArg3, Object)
    • TaskFactory.FromAsync<TArg1,TArg2,TArg3,TResult>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, TArg3, Object, TaskCreationOptions)
    • List<T>.ForEach 在修改列表项时可能会引发异常

      从 .NET Framework 4.5 开始,如果修改了调用集合中的元素,ForEach(Action<T>) 枚举器将引发 System.InvalidOperationException 异常。 该操作在以前不会引发异常,但可能会导致争用条件。

      理想情况下,应修复代码以便在枚举列表元素时不会修改列表,因为这始终不是安全操作。 但是,若要还原到以前的行为,应用可面向 .NET Framework 4.0。

      长路径支持

      从面向 .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 的应用,如果无需长路径支持,可通过将以下内容添加到 app.config 文件的 <runtime> 部分来选择弃用该支持:

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

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

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

      托管加密类不会在 FIPS 模式下引发 CryptographyException

      在 .NET framework 4.7.2 及更低版本中,当在 FIPS 模式下配置系统加密库时,SHA256Managed 等托管加密提供程序类会引发 CryptographicException。 引发这些异常的原因是托管版本未经过 FIPS(联邦信息处理标准)140-2 认证,以及没有阻止根据 FIPS 规则规定未被认可的加密算法。 由于很少有开发人员将其开发计算机置于 FIPS 模式下,因此这些异常通常仅在生产系统上引发。面向 .NET Framework 4.8 及更高版本的应用程序会自动切换到新的且宽松的策略,以便在这种情况下默认不再引发 CryptographicException。 相反,托管加密类会将加密操作重定向到系统加密库。 此系统更改可有效地删除开发人员环境和生产环境之间可能令人混淆的差异,并使本机组件和托管组件采用相同的加密策略运行。

      如果不希望出现这种情况,可以选择退出该行为并还原上述行为,方法是将以下 AppContextSwitchOverrides 配置设置添加到应用程序配置文件的 <runtime> 部分中,以便在 FIPS 模式下引发 CryptographicException

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

      如果应用程序面向 .NET Framework 4.7.2 或更低版本,则也可以通过将以下 AppContextSwitchOverrides 配置设置添加到应用程序配置文件的 <runtime> 部分来选择加入此更改:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Security.Cryptography.UseLegacyFipsThrow=false" />
      </runtime>
      
    • System.Security.Cryptography.AesManaged
    • System.Security.Cryptography.MD5Cng
    • System.Security.Cryptography.MD5CryptoServiceProvider
    • System.Security.Cryptography.RC2CryptoServiceProvider
    • System.Security.Cryptography.RijndaelManaged
    • System.Security.Cryptography.RIPEMD160Managed
    • System.Security.Cryptography.SHA1Managed
    • System.Security.Cryptography.SHA256Managed
    • ObsoleteAttribute 在 WinMD 方案中导出为 ObsoleteAttribute 和 DeprecatedAttribute

      创建 Windows 元数据库(.winmd 文件)时,System.ObsoleteAttribute 属性将导出为 System.ObsoleteAttributeWindows.Foundation.DeprecatedAttribute

      重新编译使用 System.ObsoleteAttribute 属性的现有源代码可能会在从 C++/CX 或 JavaScript 使用该代码时生成警告。我们不建议将 System.ObsoleteAttributeWindows.Foundation.DeprecatedAttribute 同时用于托管程序集中的代码,这可能会导致生成警告。

      路径冒号检查更严格

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

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

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

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

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

      Resgen 拒绝从 Web 加载内容

      .resx 文件可能包含二进制格式的输入。 如果尝试使用 resgen 来加载从不受信任的位置下载的文件,则默认情况下将无法加载该输入。

      需要从不受信任的位置加载二进制格式输入的 resgen 用户可以从输入文件中删除 Web 标记,也可以应用选择退出。添加以下注册表设置,以应用计算机范围的选择退出:[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\SDK] "AllowProcessOfUntrustedResourceFiles"="true"

      SerialPort 后台线程异常

      使用 SerialPort 流创建的后台线程不再在引发 OS 异常时终止进程。
      在面向 .NET Framework 4.7 及更早版本的应用程序中,使用 SerialPort 流创建的后台线程上引发操作系统异常时,会终止进程。
      在面向 .NET Framework 4.7.1 或更高版本的应用程序中,后台线程等待与活动串行端口相关的 OS 事件,在某些情况下(例如突然删除串行端口)也可能崩溃。

      对于面向 .NET Framework 4.7.1 的应用,如果无需异常处理,可通过将以下内容添加到 app.config 文件的 <runtime> 部分,从而选择不用异常处理:

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

      对于面向旧版 .NET Framework,但在 .NET Framework 4.7.1 或更高版本上运行的应用,可通过将以下内容添加到 app.config 文件的 <runtime> 部分来选择使用异常处理:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.IO.Ports.DoNotCatchSerialStreamThreadExceptions=false" />
      </runtime>
      

      ServiceBase 不传播 OnStart 异常

      在 .NET Framework 4.7 和更早版本中,服务启动时引发的异常不会传播到 ServiceBase.Run 的调用方。

      从面向.NET Framework 4.7.1 的应用程序开始,针对启动失败的服务,运行时会将异常传播到 ServiceBase.Run

      服务启动时,如果出现异常,将传播该异常。 这有助于诊断服务启动失败的事例。

      如果不需要此行为,可在应用程序配置文件的 runtime 部分中添加以下 AppContextSwitchOverrides 元素,从而选择弃用此行为:

      <AppContextSwitchOverrides value="Switch.System.ServiceProcess.DontThrowExceptionsOnStart=true" />
      

      如果应用程序面向早于 4.7.1 的版本,但你需要此行为,请将以下 AppContextSwitchOverrides 元素添加到应用程序配置文件的 runtime 部分:

      <AppContextSwitchOverrides value="Switch.System.ServiceProcess.DontThrowExceptionsOnStart=false" />
      

      使用便携式 PDB 时获取的堆栈跟踪现在包括源文件和行信息(如果请求)

      从 .NET Framework 4.7.2 开始,使用便携式 PDB 时获取的堆栈跟踪包括源文件和行信息(如果请求)。 在 .NET Framework 4.7.2 之前的版本中,即使已显式请求,使用便携式 PDB 时也不会提供源文件和行信息。

      对于面向 .NET Framework 4.7.2 的应用程序,如果不需要在使用便携式 PDB 时获取的源文件和行信息,可通过将以下内容添加到 app.config 文件的 <runtime> 部分,从而选择弃用:

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

      对于面向旧版 .NET Framework,但在 .NET Framework 4.7.2 或更高版本上运行的应用程序,可通过将以下内容添加到 app.config 文件的 <runtime> 部分,从而选择启用在使用便携式 PDB 时获取源文件和行信息:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Diagnostics.IgnorePortablePDBsInStackTraces=false" />
      </runtime>
      

      System.Uri 分析符合 RFC 3987

      在 .NET Framework 4.5 中,对 URI 分析做了几方面的更改。 但请注意,这些更改仅影响面向 .NET Framework 4.5 的代码。 如果二进制文件面向 .NET Framework 4.0,则将遵守旧行为。 .NET Framework 4.5 中对 URI 分析所做的更改包括:

    • URI 分析将根据 RFC 3987 中的最新 IRI 规则执行规范化和字符检查。
    • 将仅对 URI 的主机部分执行 Unicode 范式 C。
    • 无效 mailto:URI 现在会抛出异常。
    • 现在将保留路径段末尾的尾随点。
    • file:// URI 不会转义 ? 字符。
    • 不支持从 U+0080U+009F 的 Unicode 控制字符。
    • 逗号字符 ,%2c 不会自动取消转义。
    • 如果需要使用旧的 .NET Framework 4.0 URI 分析语义(通常不需要),可通过面向 .NET Framework 4.0 使用它们。 这可通过在程序集上使用 System.Runtime.Versioning.TargetFrameworkAttribute 来实现,也可以通过“项目属性”页中 Visual Studio 的项目系统 UI 来实现。

    • Uri.TryCreate(String, UriKind, Uri)
    • Uri.TryCreate(Uri, String, Uri)
    • Uri.TryCreate(Uri, Uri, Uri)
    • System.Uri.IsWellFormedUriString 方法为第一个段中具有冒号字符型的相对 URI 返回 false

      从 .NET Framework 4.5 开始,IsWellFormedUriString(String, UriKind) 会将第一个段中带有 : 的相对 URI 视为格式不正确。 这是 .NET Framework 4.0 中 System.Uri.IsWellFormedUriString(String, UriKind) 行为的更改,以符合 RFC3986。

      此更改(与许多其他 URI 更改一样)仅影响以 .NET Framework 4.5(或更高版本)为目标的应用程序。 要继续使用旧行为,请使应用以 .NET Framework 4.0 为目标。 或者,调用 System.Uri.IsWellFormedUriString(String, UriKind) 前扫描 URI,查找出于验证目的想要删除的 : 字符(如果旧行为是可取的)。

      Entity Framework 版本必须与 .NET Framework 版本匹配

      Entity Framework (EF) 版本应与 .NET Framework 版本匹配。 Entity Framework 5 推荐用于 .NET Framework 4.5。 在与 System.ComponentModel.DataAnnotations 相关的 .NET Framework 4.5 项目中,存在一些已知的 EF 4.x 问题。 在 .NET Framework 4.5 中,它们被移动到了另一程序集,因此确定要使用的注释时会出现问题。

      对于 .NET Framework 4.5 升级到 Entity Framework 5

      试用区域中不允许 IL ret

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

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

      .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 位实时编译器会在优化代码时从 catchfinally 块中删除 if 条件。 因此,catchfinally 块中的 if 语句代码会无条件地执行。
    • 已知问题的缓解措施
      如果遇到上面列出的问题,可以通过执行下列任一操作来解决:

    • 升级到 .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>
      
    • 对于每个用户,可以将名为 useLegacyJitREG_DWORD 值添加到注册表的 HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework 密钥中。 如果值为 1,可以启用旧版 64 位 JIT 编译器;如果值为 0,可以禁用旧版编译器,启用新版 64 位 JIT 编译器。

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

      ResolveAssemblyReference 任务现在将对体系结构错误的依赖项发出警告

      此任务发出警告 MSB3270,它表示引用或任何依赖项不匹配应用程序的体系结构。 例如,如果使用 AnyCPU 选项编译的应用程序包括 x86 引用,则会发生此情况。 这样的情况可能导致运行时应用失败(在本例中为,如果应用部署为 x64 过程)。

      有两方面的影响:

    • 重新编译将生成警告,当应用在以前版本的 MSBuild 下编译时,此类警告未显示。 但是,由于该警告可标识运行时失败可能的来源,所以应该调查并处理它。
    • 如果警告被视为错误,则应用将无法进行编译。
    • 证书 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>
      

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

    • System.Net.FtpWebRequest
    • ServicePointManager.SecurityProtocol 的默认值为 SecurityProtocolType.System.Default

      从面向 .NET Framework 4.7 的应用开始,ServicePointManager.SecurityProtocol 属性的默认值为 SecurityProtocolType.SystemDefault。 此更改允许基于 SslStream 的 .NET Framework 网络 API(例如 FTP、HTTPS 和 SMTP)从操作系统继承默认安全协议,而不是使用 .NET Framework 定义的硬编码值。 默认值因操作系统和系统管理员执行的任何自定义配置而异。 有关 Windows 操作系统各版本中默认 SChannel 协议的信息,请参阅 Protocols in TLS/SSL (Schannel SSP)(TLS/SSL (Schannel SSP) 中的协议)。

      对于面向 .NET Framework 早期版本的应用程序,ServicePointManager.SecurityProtocol 属性的默认值取决于所面向的 .NET Framework 版本。 请参阅“针对 .NET Framework 4.5.2 到 4.6 迁移的重定目标更改”中的“网络”部分,了解详细信息。

      此更改会影响面向 .NET Framework 4.7 或更高版本的应用程序。 如果希望使用定义协议,而不是依赖于系统默认协议,可显式设置 ServicePointManager.SecurityProtocol 属性的值。 如果不需要此更改,可在应用程序配置文件的 <runtime> 部分中添加配置设置,从而选择弃用此更改。 以下示例显示 <runtime> 部分和 Switch.System.Net.DontEnableSystemDefaultTlsVersions 选择弃用开关:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=true" />
      </runtime>
      
    • ServicePointManager.SecurityProtocol
    • System.Net.ServicePointManager 和 System.Net.Security.SslStream 中仅支持 Tls 1.0、1.1 和 1.2 协议

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

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

    • 以编程方式在 System.AppContext 上设置兼容性开关,如此处所述。
    • 在 app.config 文件的 <runtime> 部分中添加下面的代码行:
    • <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=true"/>
      

      SslStream 支持 TLS 警报

      TLS 握手失败后,第一个 I/O 读取/写入操作将引发带有内部 System.ComponentModel.Win32Exception 异常的 System.IO.IOException。 可以使用 TLS 和 SSL 警报的 Schannel 错误代码System.ComponentModel.Win32ExceptionSystem.ComponentModel.Win32Exception.NativeErrorCode 代码从远程参与方映射到 TLS 警报。有关详细信息,请参阅 RFC 2246:第 7.2.2 节错误警报
      .NET Framework 4.6.2 及更早版本中的行为是:如果另一方握手失败然后立即拒绝连接,则传输通道(通常为 TCP 连接)将在写入或读取时超时。

      调用网络 I/O API(例如 Read(Byte[], Int32, Int32)/Write(Byte[], Int32, Int32))的应用程序应处理 IOExceptionSystem.TimeoutException
      从 .NET Framework 4.7 开始,TLS 警报功能将默认启用。 在 .NET Framework 4.7 或更高系统上运行的面向 .NET Framework 4.0 到 4.6.2 版本的应用程序将禁用该功能以保留兼容性。
      以下配置 API 用于为在 .NET Framework 4.7 或更高版本上运行的 .NET Framework 4.6 和更高版本应用程序启用或禁用该功能。

    • 以编程方式:必须是应用程序执行的第一件事,因为 ServicePointManager 将只初始化一次:

      AppContext.SetSwitch("TestSwitch.LocalAppContext.DisableCaching", true);
      // Set to 'false' to enable the feature in .NET Framework 4.6 - 4.6.2.
      AppContext.SetSwitch("Switch.System.Net.DontEnableTlsAlerts", true);
      
    • AppConfig:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Net.DontEnableTlsAlerts=true"/>
        <!-- Set to 'false' to enable the feature in .NET Framework 4.6 - 4.6.2. -->
      </runtime>
      
    • 注册表项(计算机全局):将值设置为 false,以在 .NET Framework 4.6 - 4.6.2 中启用该功能。

      Key: HKLM\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AppContext\Switch.System.Net.DontEnableTlsAlerts
      - Type: String
      - Value: "true"
      

      默认情况下,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 将要加密的数据拆分为两个单独的记录,第一个为 1 个字节,第二个为 n-1 个字节。在极少数情况下,如果假定数据驻留在一个记录中,则客户端与现有服务器之间的通信会中断。

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

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

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

      CspParameters.ParentWindowHandle 现在需要 HWND 值

      借助 .NET Framework 2.0 中引入的 ParentWindowHandle 值,应用程序可以注册父窗口句柄值,这样任何需要访问密钥的 UI(如 PIN 提示或同意对话框)将会作为指定窗口的子模式打开。从面向 .NET Framework 4.7 的应用开始,Windows 窗体应用程序可使用如下所示的代码设置 ParentWindowHandle 属性:

      cspParameters.ParentWindowHandle = form.Handle;
      

      在先前版本的 .NET Framework 中,该值应为 System.IntPtr,表示内存中驻留 HWND 值的位置。 在 Windows 7 和更低版本上,将属性设置为 form.Handle 不会造成任何影响,但在 Windows 8 和更高版本中,此操作会导致“System.Security.Cryptography.CryptographicException:参数不正确。”

      如果应用程序要注册父窗口关系且面向 .NET Framework 4.7 或更高版本,建议使用简易窗体:

      cspParameters.ParentWindowHandle = form.Handle;
      

      如果用户已确定要传递的正确值是保留 form.Handle 值的内存位置地址,可通过将 AppContext 开关 Switch.System.Security.Cryptography.DoNotAddrOfCspParentWindowHandle 设置为 true 来选择弃用此行为更改:

    • 以编程方式在 AppContext 上设置兼容性开关,如此处所述。
    • 在 app.config 文件的 <runtime> 部分中添加下面的代码行:
    • <runtime>
       <AppContextSwitchOverrides value="Switch.System.Security.Cryptography.DoNotAddrOfCspParentWindowHandle=true"/>
      </runtime>
      

      相反,如果用户希望在旧版 .NET Framework 中加载应用程序时选择启用 .NET Framework 4.7 运行时上的新行为,则可将 AppContext 开关设置为 false

      默认的 SignedXML 和 SignedXMS 算法已更改为 SHA256

      在 .NET Framework 4.7 及早期版本中,SignedXML 和 SignedCMS 默认为 SHA1 以执行某些操作。从 .NET Framework 4.7.1 开始,默认情况下启用 SHA256 来执行这些操作。 此更改是必需的,因为 SHA1 不再是安全的。

      有两个新的上下文切换值,用于控制默认情况下使用 SHA1(不安全)还是 SHA256:

    • Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms
    • Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms 对于面向 .NET Framework 4.7.1 及更高版本的应用程序,如果不希望使用 SHA256,则可通过将以下配置开关添加到应用配置文件的运行时部分,将默认值还原为 SHA1:
    • <AppContextSwitchOverrides value="Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms=true;Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms=true" />
      

      对于面向 .NET Framework 4.7 及更高版本的应用程序,可通过将以下配置开关添加到应用配置文件的运行时部分,来选择使用此更改:

      <AppContextSwitchOverrides value="Switch.System.Security.Cryptography.Xml.UseInsecureHashAlgorithms=false;Switch.System.Security.Cryptography.Pkcs.UseInsecureHashAlgorithms=false" />
      
    • System.Security.Cryptography.Pkcs.CmsSigner
    • System.Security.Cryptography.Xml.SignedXml
    • System.Security.Cryptography.Xml.Reference
    • 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,请考虑删除该逻辑。

    • RSA.ImportParameters(RSAParameters)
    • RSACng.ImportParameters(RSAParameters)
    • RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2)
    • RSACertificateExtensions.GetRSAPublicKey(X509Certificate2)
    • SslStream 支持 TLS 警报

      TLS 握手失败后,第一个 I/O 读取/写入操作将引发带有内部 System.ComponentModel.Win32Exception 异常的 System.IO.IOException。 可以使用 TLS 和 SSL 警报的 Schannel 错误代码System.ComponentModel.Win32ExceptionSystem.ComponentModel.Win32Exception.NativeErrorCode 代码从远程参与方映射到 TLS 警报。有关详细信息,请参阅 RFC 2246:第 7.2.2 节错误警报
      .NET Framework 4.6.2 及更早版本中的行为是:如果另一方握手失败然后立即拒绝连接,则传输通道(通常为 TCP 连接)将在写入或读取时超时。

      调用网络 I/O API(例如 Read(Byte[], Int32, Int32)/Write(Byte[], Int32, Int32))的应用程序应处理 IOExceptionSystem.TimeoutException
      从 .NET Framework 4.7 开始,TLS 警报功能将默认启用。 在 .NET Framework 4.7 或更高系统上运行的面向 .NET Framework 4.0 到 4.6.2 版本的应用程序将禁用该功能以保留兼容性。
      以下配置 API 用于为在 .NET Framework 4.7 或更高版本上运行的 .NET Framework 4.6 和更高版本应用程序启用或禁用该功能。

    • 以编程方式:必须是应用程序执行的第一件事,因为 ServicePointManager 将只初始化一次:

      AppContext.SetSwitch("TestSwitch.LocalAppContext.DisableCaching", true);
      // Set to 'false' to enable the feature in .NET Framework 4.6 - 4.6.2.
      AppContext.SetSwitch("Switch.System.Net.DontEnableTlsAlerts", true);
      
    • AppConfig:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Net.DontEnableTlsAlerts=true"/>
        <!-- Set to 'false' to enable the feature in .NET Framework 4.6 - 4.6.2. -->
      </runtime>
      
    • 注册表项(计算机全局):将值设置为 false,以在 .NET Framework 4.6 - 4.6.2 中启用该功能。

      Key: HKLM\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AppContext\Switch.System.Net.DontEnableTlsAlerts
      - Type: String
      - Value: "true"
      

      VB.NET 不再支持 System.Windows API 的部分命名空间限定

      从 .NET Framework 4.5.2 开始,VB.NET 项目无法通过部分限定命名空间指定 System.Windows API。 例如,对 Windows.Forms.DialogResult 的引用将失败。 而代码必须引用完全限定名称 (DialogResult),或导入特定命名空间并仅引用 System.Windows.Forms.DialogResult

      应更新代码,以使用简单名称(并导入相关命名空间)或使用完全限定名称来引用 System.Windows 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" />
      

      受影响的 API

    • AuthorizationContext.CreateDefaultAuthorizationContext(IList<IAuthorizationPolicy>)
    • 使用可重入服务时可能导致死锁

      死锁可能会导致一个可重入服务,该服务将服务的实例一次限制为一个执行线程。 代码中包含以下 ServiceBehaviorAttribute 的服务容易遇到此问题:

      [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
      

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

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

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

      某些 .NET SDK 工具的改进的辅助功能

      在 .NET Framework SDK 4.7.1 中,已通过修复各种辅助功能问题,改进了 SvcConfigEditor.exe 和 SvcTraceViewer.exe 工具。 其中大多数都是一些小问题,如未定义名称或未正确实现某些 UI 自动化模式。 虽然许多用户不会意识到这些小问题的重要性,但使用屏幕阅读器等辅助技术的客户会发现这些 SDK 工具更易于访问。 当然,这些修复程序改变了以前的某些行为,如键盘焦点顺序。为获取这些工具中的所有辅助功能修复程序,可对 app.config 文件执行以下操作:

      <runtime>
        <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false"/>
      </runtime>
      

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

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

    • 在返回 TaskTask<TResult> 的方法中检索 OperationContext.Current 属性的值。
    • using 子句中实例化 OperationContextScope 对象。
    • using statement 中检索 OperationContext.Current 属性的值。 例如:
    • 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。 这将禁用 OperationContext.Current 中的 ExecutionContext 流并还原 .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>
      

      使用 DataContractJsonSerializer 控制字符的序列化现在与 ECMAScript V6 和 V8 兼容

      在 .NET Framework 4.6.2 及更低版本中,System.Runtime.Serialization.Json.DataContractJsonSerializer 未按与 ECMAScript V6 和 V8 标准兼容的方式对一些特殊控制字符(如 \b、\f 和 \t)进行序列化。 从 .NET Framework 4.7 开始,这些控制字符的序列化与 ECMAScript V6 和 V8 兼容。

      对面向 .NET Framework 4.7 的应用,默认启用此功能。 如果不需要此行为,可以在 app.config 或 web.config 文件的 <runtime> 部分中添加下面的代码行,从而选择禁用此功能:

      <runtime>
        <AppContextSwitchOverrides value="Switch.System.Runtime.Serialization.DoNotUseECMAScriptV6EscapeControlCharacter=false" />
      </runtime>
      
    • DataContractJsonSerializer.WriteObject(Stream, Object)
    • DataContractJsonSerializer.WriteObject(XmlDictionaryWriter, Object)
    • DataContractJsonSerializer.WriteObject(XmlWriter, Object)
    • 与 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>
      
    • BasicHttpSecurityMode.TransportWithMessageCredential
    • BasicHttpsSecurityMode.TransportWithMessageCredential
    • SecurityMode.TransportWithMessageCredential
    • WSFederationHttpSecurityMode.TransportWithMessageCredential
    • 现在,WCF 消息安全性能够使用 TLS1.1 和 TLS1.2

      从 .NET Framework 4.7 开始,除 SSL3.0 和 TLS1.0 之外,客户还可通过应用程序配置设置在 WCF 消息安全性中配置 TLS1.1 或 TLS1.2。

      在 .NET Framework 4.7 中,默认情况下禁用 WCF 消息安全性中对 TLS1.1 和 TLS1.2 的支持。 可通过将以下行添加到 app.config 或 web.config 文件的 <runtime> 部分来启用支持:

      <runtime>
      <AppContextSwitchOverrides value="Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false" />
      </runtime>
      

      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 证书启动安全通信的异常处理代码。

      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 之前的版本,将启用此更改)。

      适用于 .NET 4.7.2 的 Windows 窗体控件中的辅助功能改进

      Windows 窗体框架正在改进其辅助功能技术的工作方式,以更好地支持 Windows 窗体客户。 其中包括以下更改:

    • 改进高对比度模式的显示效果。
    • 用于改进 DataGridView 和 MenuStrip 控件中的键盘导航的更改。
    • 对讲述人交互的更改。
    • 如何选择启用或选择弃用这些更改 为使应用程序从这些更改获益,它必须在 .NET Framework 4.7.2 或更高版本上运行。 此应用程序可通过以下任何一种方式从这些更改中获益:

    • 重新编译为面向 .NET Framework 4.7.2。 对于面向 .NET Framework 4.7.2 或更高版本的 Windows 窗体 应用程序,这些辅助功能更改将默认启用。
    • 它面向 .NET Framework 4.7.1 或更早版本,通过向 app config 文件的 <runtime> 部分添加以下 AppContext 开关并将其设置为 false,可选择弃用旧版辅助功能行为,如下例所示。
    • <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <startup>
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
        </startup>
        <runtime>
          <!-- AppContextSwitchOverrides value attribute is in the form of 'key1=true/false;key2=true/false  -->
          <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false;Switch.UseLegacyAccessibilityFeatures.2=false" />
        </runtime>
      </configuration>
      

      请注意,要选择启用 .NET Framework 4.7.2 中添加的辅助功能,还必须选择启用 .NET Framework 4.7.1 的辅助功能。 面向 .NET Framework 4.7.2 或更高版本并希望保留旧版辅助功能行为的应用程序,可通过将此 AppContext 开关显式设置为 true 来选择启用旧版辅助功能。

      在高对比度主题中使用 OS 定义的颜色

    • ToolStripDropDownButton 的下拉菜单现在在高对比度主题中使用 OS 定义的颜色。
    • 现在,在高对比度主题中选中将 ButtonRadioButtonCheckBox 控件的 FlatStyle 设置为 FlatStyle.FlatFlatStyle.Popup 时,它们会使用 OS 定义的颜色。 以前,文本和背景颜色对比度低,难以阅读。
    • 包含在 GroupBox(其 Enabled 属性设置为 false)中的控件现在将在高对比度主题中使用 OS 定义的颜色。
    • 在高对比度模式下,ToolStripButtonToolStripComboBoxToolStripDropDownButton 控件的亮度对比度提高。
    • 对于 DataGridViewLinkCell.LinkColor 属性,DataGridViewLinkCell 将默认使用高对比模式下 OS 定义的颜色。 注意:Windows 10 已更改部分高对比度系统颜色的值。 Windows 窗体框架基于 Win32 框架。 为获得最佳体验,请运行最新版本的 Windows,并通过在测试应用程序中添加 app.manifest 文件选择使用最新的 OS 更改,同时取消注释以下代码:
    • <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
      

      改进了讲述人支持

    • 现在,讲述人将在公布 ToolStripMenuItem 的文本时公布 ToolStripMenuItem.ShortcutKeys 属性的值。
    • ToolStripMenuItemEnabled 属性设置为 false 时,讲述人现在会有所指示。
    • ListView.CheckBoxes 属性设置为 true 时,讲述人现在会针对复选框的状态给出反馈。
    • 讲述人扫描模式焦点顺序现在与 ClickOnce 下载对话框窗口中控件的视觉顺序一致。
    • 改进了 DataGridView 辅助功能支持

    • DataGridView 中的行现在可使用键盘进行排序。 现在用户可使用 F3 键按当前列排序。
    • DataGridView.SelectionMode 设置为 DataGridViewSelectionMode.FullRowSelect,当用户按 Tab 键遍历当前行中的单元格时,列标题将更改颜色来指示当前列。
    • DataGridViewCell.DataGridViewCellAccessibleObject.Parent 属性现在返回正确的父控件。
    • 改进了视觉提示

    • 具有空 Text 属性的 RadioButtonCheckBox 控件现在将在接收到焦点时显示焦点指示器。
    • 改进了属性网格支持

    • 现在,仅在 PropertyGrid 元素启用时,PropertyGrid 控件子元素才会为 IsReadOnlyProperty 属性返回 true

    • 现在,仅在用户可更改 PropertyGrid 元素时,PropertyGrid 控件子元素才会为 IsEnabledProperty 属性返回 false。 有关 UI 自动化的概述,请参阅 UI 自动化概述

      改进了的键盘导航
    • ToolStripButton 包含在将 TabStop 属性设置为 trueToolStripPanel 中时,现在允许聚焦。

      适用于 .NET 4.8 的 Windows 窗体控件中的辅助功能改进

      Windows 窗体框架持续改进其与辅助功能技术的协作方式,以更好地支持 Windows 窗体客户。 其中包括以下更改:

    • 改进高对比度模式的显示效果。
    • 对讲述人交互的更改。
    • 辅助功能层次结构中的更改(通过 UI 自动化树改进导航)。
    • 如何选择加入或选择退出这些更改 为使应用程序从这些更改中获益,它必须在 .NET Framework 4.8 上运行。 应用程序可通过以下任一方式选择加入这些更改:

    • 重新编译为面向 .NET Framework 4.8。 对于面向 .NET Framework 4.8 的 Windows 窗体应用程序,这些辅助功能更改将默认启用。
    • 它面向 .NET Framework 4.7.2 或更低版本,通过向应用配置文件的 <runtime> 部分添加以下 AppContext 开关并将其设置为 false,可选择弃用旧版辅助功能行为,如下例所示。
    • <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <startup>
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
        </startup>
        <runtime>
          <!-- AppContextSwitchOverrides value attribute is in the form of 'key1=true/false;key2=true/false  -->
          <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false;Switch.UseLegacyAccessibilityFeatures.2=false;Switch.UseLegacyAccessibilityFeatures.3=false" />
        </runtime>
      </configuration>
      

      请注意,要选择加入 .NET Framework 4.8 中添加的辅助功能,还必须选择加入 .NET Framework 4.7.1 及 4.7.2 的辅助功能。 面向 .NET Framework 4.8 且希望保留旧版辅助功能行为的应用程序可以通过将此 AppContext 开关显式设置为 true 来选择加入使用旧版辅助功能。启用键盘 ToolTip 调用支持需要将 Switch.System.Windows.Forms.UseLegacyToolTipDisplay=false 行添加到 AppContextSwitchOverrides 值:

      <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false;Switch.UseLegacyAccessibilityFeatures.2=false;Switch.UseLegacyAccessibilityFeatures.3=false;Switch.System.Windows.Forms.UseLegacyToolTipDisplay=false" />
      

      请注意,启用此功能需要选择加入上述 .NET Framework 4.7.1 到 4.8 的辅助功能。 此外,如果未选择加入任何辅助功能,但选择加入了工具提示显示功能,则首次访问这些功能时将引发运行时 NotSupportedException。 异常消息表明键盘工具提示需要启用第 3 级辅助功能改进。

      在高对比度主题中使用 OS 定义的颜色

    • 改进了高对比度主题。
    • 改进了讲述人支持

    • 在说出 DataGridViewCell 的辅助功能名称时,讲述人现在会说出 DataGridViewColumn 的排序方向。
    • 改进了 CheckedListBox 辅助功能支持

    • 改进了 CheckedListBox 控件的讲述人支持。 使用键盘导航到 CheckedListBox 控件时,讲述人会聚焦 CheckedListBox 项并说出该项。
    • 控件变得聚焦时,空的 CheckedListBox 控件现包含为第一个虚拟项绘制的焦点矩形。
    • 改进了 ComboBox 辅助功能支持

    • ComboBox 控件启用了 UI 自动化支持,并且可以使用 UI 自动化通知和其他 UI 自动化功能。 改进了 DataGridView 辅助功能支持

    • DataGridView 控件启用了 UI 自动化支持,并且可以使用 UI 自动化通知和其他 UI 自动化功能。

    • 对应于 DataGridViewComboBoxEditingControlDataGridViewTextBoxEditingControl 的 UI 自动化元素现在是相应编辑单元的子元素。

      改进了 LinkLabel 辅助功能支持

    • 改进了 LinkLabel 控件辅助功能:如果禁用了对应的 LinkLabel 控件,讲述人会指示链接的禁用状态。
    • 改进了 ProgressBar 辅助功能支持

    • ProgressBar 控件启用了 UI 自动化支持,并且可以使用 UI 自动化通知和其他 UI 自动化功能。 开发人员现可使用 UI 自动化通知,讲述人可以通过这些通知来指示进度。 有关 UI 自动化事件概述(包括 UI 自动化通知事件)的概述,请参阅 UI 自动化事件概述
    • 改进了 PropertyGrid 辅助功能支持

    • PropertyGrid 控件启用了 UI 自动化支持,并且可以使用 UI 自动化通知和其他 UI 自动化功能。
    • 与当前编辑的属性对应的 UI 自动化元素现在是对应属性项 UI 自动化元素的子元素。
    • 如果父 PropertyGrid 控件设置为类别视图,则 UI 自动化属性项元素现在是对应类别元素的子元素。
    • 改进了 ToolStrip 支持

    • ToolStrip 控件启用了 UI 自动化支持,并且可以使用 UI 自动化通知和其他 UI 自动化功能。
    • 改进了对 ToolStrip 项的导航。
    • 在项模式下,讲述人焦点不会消失,也不会转到隐藏项。
    • 改进了视觉提示

    • 空的 CheckedListBox 控件现在在接收焦点时显示焦点指示器。 注意:在运行时为控件启用了 UI 自动化支持,但设计时未使用该支持。 有关 UI 自动化的概述,请参阅 UI 自动化概述
    • 通过键盘调用控件的工具提示

    • 现可通过使用键盘聚焦控件来调用控件工具提示。 应用程序必须显式启用此功能(请参阅“如何选择加入或退出这些更改”部分)
    • Windows 窗体控件中的辅助功能改进

      Windows 窗体正在使用辅助功能技术改进工作方式,以更好地支持 Windows 窗体客户。 包括从 .NET Framework 4.7.1 开始的以下改进:

    • 改进高对比度模式的显示效果。
    • 提升属性浏览器体验。 属性浏览器改进包括:
    • 更好地通过各种下拉选择窗口使用键盘导航。
    • 减少不必要的制表位。
    • 更好地报告控件类型。
    • 改进了讲述人行为。
    • 在控件中实现缺少 UI 辅助功能模式。
    • 如何选择启用或选择弃用这些更改 为使应用程序从这些更改获益,它必须在 .NET Framework 4.7.1 或更高版本上运行。 此应用程序可通过以下任何一种方式从这些更改中获益:

    • 重新编译为面向 .NET Framework 4.7.1。 对于面向 .NET Framework 4.7.1 或更高版本的 Windows 窗体 应用程序,这些辅助功能默认情况下处于启用状态。
    • 通过向 app config 文件的 <runtime> 部分添加以下 AppContext 交换机并将其设置为 false,可选择退出旧版辅助功能行为,如下例所示。
    • <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <startup>
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
        </startup>
        <runtime>
          <!-- AppContextSwitchOverrides value attribute is in the form of 'key1=true/false;key2=true/false  -->
          <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false" />
        </runtime>
      </configuration>
      

      面向 .NET Framework 4.7.1 或更高版本并希望保留旧版辅助功能行为的应用程序,可通过将此 AppContext 开关显式设置为 true 来选择启用旧版辅助功能。

      有关 UI 自动化的概述,请参阅 UI 自动化概述

      为 UI 自动化模式和属性添加的支持
      辅助功能客户端可通过使用常用的公开描述调用模式来利用新的 WinForms 辅助功能。 这些模式并非特定于 WinForms。 例如,辅助功能客户端可以在 IAccessible 接口 (MAAS) 上调用 QueryInterface 方法,来获取 IServiceProvider 接口。 如果该接口可用,则客户端可以使用其 QueryService 方法来请求 IAccessibleEx 接口。 有关详细信息,请参阅从客户端使用 IAccessibleEx。 从 .NET Framework 4.7.1 开始,IServiceProvider 和 IAccessibleEx(在适用情况下)可用于 WinForms 辅助功能对象。

      .NET Framework 4.7.1 为以下 UI 自动化模式和属性添加支持:

    • ToolStripSplitButtonComboBox 控件支持展开/折叠模式

    • ToolStripMenuItem 控件具有 ControlType 属性值 ControlType.MenuItem

    • ToolStripItem 控件支持 NameProperty 属性和展开/折叠模式

    • ToolStripDropDownItem 控件支持 AccessibleEvents 在下拉列表展开或折叠时指示 StateChange 和 NameChange。

    • ToolStripDropDownButton 控件具有 ControlType.MenuItemControlType 属性值。

    • DataGridViewCheckBoxCell 控件支持 TogglePattern

    • NumericUpDownDomainUpDown 控件支持 NameProperty 属性并具有 ControlType.SpinnerControlType

      对 PropertyGrid 控件的改进 .NET Framework 4.7.1 向 PropertyBrowser 控件添加了以下改进:
    • 用户在 PropertyGrid 控件中输入错误值时所显示错误对话框中的“详细信息”按钮支持展开/折叠模式、状态和名称更改通知以及带有 ControlType.MenuItem 值的 ControlType 属性。

    • 展开错误对话框的“详细信息”按钮时显示的信息窗格,现在可以通过键盘访问并允许讲述人宣布错误信息内容。

    • PropertyGrid 控件中行的 AccessibleRole 已从“行”更改为“单元格”。 单元格映射到 UIA ControlType“DataItem”,使其能够支持相应的键盘快捷方式和讲述人朗读。

    • PropertyGrid 控件行,当 PropertyGrid 控件设置为 PropertySort.CategorizedPropertySort 属性具有 ControlType.ButtonControlType 属性值时,它代表标头项。

    • PropertyGrid 控件的 PropertySort 属性设置为 PropertySort.Categorized 时,代表标头项的 PropertyGrid 控件行支持展开/折叠模式

    • 改进了网格与其上工具栏之间的键盘导航。 现在按“Shift-Tab”会选中第一个工具栏按钮,而不是整个工具栏。

    • 在高对比度模式中显示的 PropertyGrid 控件现在将围绕与当前 PropertySort 属性值相对应的工具栏按钮绘制焦点矩形。

    • 在高对比度模式中显示 PropertyGrid 控件且 PropertySort 属性设置为 PropertySort.Categorized,现在将以高对比度颜色显示类别标题的背景。

    • PropertyGrid 控件更好地区分具有焦点的工具栏项和指示 PropertySort 属性当前值的工具栏项。 此修补程序包含高对比度更改和非高对比度方案的更改。

    • 指示 PropertySort 属性当前值的 PropertyGrid 控件工具栏项支持 TogglePattern

    • 改进的讲述人支持在对齐方式选择器中区分所选对齐。

    • 当窗体上显示空 PropertyGrid 控件时,现可将焦点置于其上,而之前不能。

      在高对比度主题中使用 OS 定义的颜色

    • ButtonCheckBox 控件的 FlatStyle 属性设置为 FlatStyle.System(默认样式),现在,在高对比度主题中选中这两个控件时,它们会使用 OS 定义的颜色。 以前,文本和背景颜色对比度低,难以阅读。
    • ButtonCheckBoxRadioButtonLabelLinkLabelGroupBox 控件及其设置为“false”的 Enabled 属性在高对比度主题中使用阴影颜色呈现文本,从而降低与背景的对比度。 现在这些控件使用 OS 定义的“无效文本”颜色。 此修补程序适用于将 FlatStyle 属性设置为某个值而不是 FlatStyle.System 的控件。 后一种控件由 OS 呈现。
    • DataGridView 现在围绕具有当前焦点的单元内容呈现可见的矩形。 以前,在某些高对比度主题中这是不可见的。
    • Enabled 属性设置为“false”的 ToolStripMenuItem 控件现在使用 OS 定义的“无效文本”颜色。
    • Checked 属性设置为“true”的 ToolStripMenuItem 控件现以系统颜色的对比色呈现相关复选标记。 以前,复选标记颜色的对比度不足,在高对比度主题中不可见。 注意:Windows 10 已更改部分高对比度系统颜色的值。 Windows 窗体框架基于 Win32 框架。 为获得最佳体验,请运行最新版本的 Windows,并通过在测试应用程序中添加 app.manifest 文件选择使用最新的 OS 更改,同时取消注释以下代码:
    • <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
      

      改进了的键盘导航

    • ComboBox 控件将其 DropDownStyle 属性设置为 ComboBoxStyle.DropDownList 并且为窗体上 Tab 键顺序中的第一个控件时,在使用键盘打开父级窗体时,该控件现在将显示焦点矩形。 在此更改之前,键盘焦点在控件上,但不会呈现焦点指示器。
    • 改进了讲述人支持

    • MonthCalendar 控件对访问控件添加了辅助技术支持,包括使讲述人朗读控件值的功能(以前无法读取)。

    • CheckBox.CheckState 属性发生更改时,CheckedListBox 控件现在会通知讲述人。 以前,讲述人不会收到通知,因此在 CheckState 属性更新时,用户也不会收到通知。

    • LinkLabel 控件更改了通知讲述人控件文本的方式。 以前,讲述人朗读此文本两次并将“&”符号作为实际文本进行朗读,即使这些符号对用户不可见。 现已从讲述人朗读中删除重复的文本以及不必要的“&”符号。

    • DataGridViewCell 控件类型现在正确地向讲述人和其他辅助技术报告只读状态。

    • 讲述人现在可在 [多文档界面]~/docs/framework/winforms/advanced/multiple-document-interface-mdi-applications.md) 应用程序中读取子窗口的系统菜单。

    • 讲述人现在能朗读将 ToolStripItem.Enabled 属性设置为 falseToolStripMenuItem 控件。 以前,讲述人无法将焦点置于已禁用的菜单项来朗读内容。

    • ToolStripDropDownButton.CreateAccessibilityInstance()
    • DomainUpDown.DomainUpDownAccessibleObject.Name
    • MonthCalendar.AccessibilityObject
    • IMessageFilter.PreFilterMessage 的可重入实现不会再引发 Application.FilterMessage

      在 .NET Framework 4.6.1 之前,使用名为 System.Windows.Forms.Application.AddMessageFilter(IMessageFilter)System.Windows.Forms.Application.RemoveMessageFilter(IMessageFilter)PreFilterMessage(Message) 调用 FilterMessage(Message)(同时调用 DoEvents())会导致 System.IndexOutOfRangeException

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

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

    • Application.FilterMessage(Message)
    • 存在嵌套 ToolStripMenuItems 时,ContextMenuStrip.SourceControl 属性包含有效控件

      在 .NET Framework 4.7.1 和更早版本中,用户从嵌套 ToolStripMenuItem 控件中打开菜单时,ContextMenuStrip.SourceControl 属性会错误地返回 null。 在 .NET Framework 4.7.2 及更高版本中,SourceControl 属性始终设置为实际的源代码管理。

      如何选择启用或选择弃用这些更改 为使应用程序从这些更改获益,它必须在 .NET Framework 4.7.2 或更高版本上运行。 此应用程序可通过以下任何一种方式从这些更改中获益:

    • 它面向 .NET Framework 4.7.2。 对于面向 .NET Framework 4.7.2 或更高版本的 Windows 窗体应用程序,此更改将默认启用。
    • 它面向 .NET Framework 4.7.1 或更早版本,通过向 app.config 文件的 <runtime> 部分添加以下 AppContext 开关并将其设置为 false,可选择弃用旧版辅助功能行为,如下例所示。
    • <runtime>
        <AppContextSwitchOverrides value="Switch.System.Windows.Forms.UseLegacyContextMenuStripSourceControlValue=false"/>
      </runtime>
      

      面向 .NET Framework 4.7.2 或更高版本并希望保留旧版行为的应用程序,可通过将此 AppContext 开关显式设置为 true 来选择启用旧版源代码管理值。

      DataObject.GetData 现在将数据检索为 UTF-8

      对于面向 .NET Framework 4 或者在 .NET Framework 4.5.1 或更早版本上运行的应用,DataObject.GetData 将 HTML 格式的数据检索为 ASCII 字符串。 因此,非 ASCII 字符(ASCII 代码大于 0x7F 的字符)由两个随机字符表示。

      对于面向 .NET Framework 4.5 或更高版本以及在 .NET Framework 4.5.2 上运行的应用,DataObject.GetData 将按 UTF-8 检索 HTML 格式的数据,从而可以正确表示大于 0x7F 的字符。

      如果使用 HTML 格式的字符串实现了编码问题的解决方法(例如,通过将其传递到 System.Text.UTF8Encoding.GetString(Byte[], Int32, Int32) 来显式编码从剪贴板检索的 HTML 字符串),而且要将应用的目标从版本 4 重定为 4.5,则应该删除该解决方法。如果出于某种原因需要使用以前的版本,该应用可面向 .NET Framework 4.0 来获取该行为。

      EncoderParameter ctor 已过时

      EncoderParameter(Encoder, Int32, Int32, Int32, Int32) 构造函数现已过时,使用它将引发生成警告。

      虽然 EncoderParameter(Encoder, Int32, Int32, Int32, Int32) 构造函数仍将继续有效,但还是应该改用以下构造函数,以避免在使用 .NET Framework 4.5 工具重新编译代码时出现已过时的生成警告:EncoderParameter(Encoder, Int32, EncoderParameterValueType, IntPtr)

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

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

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

      此更改影响重新编译为面向 .NET Framework 4.6 的应用以及针对图标对象具有 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>" />
      

      MemberDescriptor.Equals 实现不正确

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

      描述符相等时如果应用程序依赖于有时返回 falseMemberDescriptor.Equals 并且你面向 .NET Framework 4.6.2 和更高版本,那么可以采用以下几个选项:

    • 除了调用 MemberDescriptor.Equals 方法,还需更改代码来手动比较 CategoryDescription 字段。
    • 将以下值添加到 app.config 文件从而选择弃用此更改:
    • <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>
      

      PrivateFontCollection.AddFontFile 方法释放字体资源

      在 .NET Framework 4.7.1 和早期版本中,为使用 AddFontFile(String) 方法添加到此集合的 Font 对象设置 PrivateFontCollection 后,System.Drawing.Text.PrivateFontCollection 类不会释放 GDI+ 字体资源。 在 .NET Framework 4.7.2 和更高版本中,Dispose 会释放作为文件添加到此集合的 GDI+ 字体。

      如何选择启用或选择弃用这些更改 为使应用程序从这些更改获益,它必须在 .NET Framework 4.7.2 或更高版本上运行。 此应用程序可通过以下任何一种方式从这些更改中获益:

    • 重新编译为面向 .NET Framework 4.7.2。 对于面向 .NET Framework 4.7.2 或更高版本的 Windows 窗体应用程序,此更改将默认启用。
    • 它面向 .NET Framework 4.7.1 或更早版本,通过向 app.config 文件的 <runtime> 部分添加以下 AppContext 开关并将其设置为 false,可选择弃用旧版辅助功能行为,如下例所示。
    • <runtime>
      <AppContextSwitchOverrides value="Switch.System.Drawing.Text.DoNotRemoveGdiFontsResourcesFromFontCollection=false"/>
      </runtime>
      

      面向 .NET Framework 4.7.2 或更高版本并希望保留旧版行为的应用程序,可通过将此 AppContext 开关显式设置为 true 来选择不释放字体资源。

      WinForm 的域 upbutton 和 downbutton 操作现已同步

      在 .NET Framework 4.7.1 和早期版本中,显示控件文本时会忽视 DomainUpDown 控件的 DomainUpDown.UpButton() 操作,并且要求开发人员先使用控件上的 DomainUpDown.DownButton() 操作,再使用 DomainUpDown.UpButton() 操作。 从 .NET Framework 4.7.2 开始,DomainUpDown.UpButton()DomainUpDown.DownButton() 操作将在此场景中独立工作,并保持同步。

      为使应用程序从这些更改获益,它必须在 .NET Framework 4.7.2 或更高版本上运行。 此应用程序可通过以下任何一种方式从这些更改中获益:

    • 重新编译为面向 .NET Framework 4.7.2。 对于面向 .NET Framework 4.7.2 或更高版本的 Windows 窗体应用程序,此更改将默认启用。
    • 通过向应用配置文件的 <runtime> 部分添加以下 AppContext 开关并将其设置为 false,可选择弃用旧版滚动行为,如下例所示。
    • <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Forms.DomainUpDown.UseLegacyScrolling=false"/>
      </runtime>
      
    • Expander 控件的焦点现在可见。 在先前版本的 .NET Framework 中,并非如此。
    • CheckBoxRadioButton 控件中的文本在选中时,比之前的 .NET Framework 版本更易查看。
    • 现在已禁用的 ComboBox 的边框颜色与已禁用的文本颜色相同。 在先前版本的 .NET Framework 中,并非如此。
    • 禁用和聚焦的按钮现在使用正确的主题颜色。 在先前版本的 .NET Framework 中,并未如此。
    • ComboBox 控件的样式设置为 ToolBar.ComboBoxStyleKey 时,下拉按钮现在可见。 在先前版本的 .NET Framework 中,并非如此。
    • DataGrid 控件中的排序指示器箭头现在可使用主题颜色。 在先前版本的 .NET Framework 中,并非如此。
    • 默认超链接样式更改为在鼠标悬停时显示正确的主题颜色。 在先前版本的 .NET Framework 中,并非如此。
    • 单选按钮上的键盘焦点现在可见。 在先前版本的 .NET Framework 中,并非如此。
    • 现在 DataGrid 控件的复选框列对键盘焦点反馈使用预期的颜色。 在先前版本的 .NET Framework 中,并非如此。
    • 现在,键盘焦点视觉对象在 ComboBoxListBox 控件上可见。 在先前版本的 .NET Framework 中,并非如此。
    • 屏幕阅读器交互改进

    • 屏幕阅读器现在正确地将 Expander 控件称为组(展开/折叠)。
    • 屏幕阅读器现在正确地将 DataGridCell 控件称为数据网格单元格(已本地化)。
    • 屏幕阅读器现在将宣布可编辑的 ComboBox 的名称。
    • 屏幕阅读器不再将 PasswordBox 控件读作“视图中没有任何项”。
    • LiveRegion 支持

      屏幕阅读器(例如讲述人)可帮助用户理解应用程序的用户界面 (UI),这通常是通过描述当前具有焦点的 UI 元素来实现的。 但是,如果 UI 元素更改了屏幕中某些地方,并且不具有焦点,则用户可能不会收到通知,并且错过重要信息。 LiveRegions 旨在解决此问题。 开发人员可使用它们来通知屏幕阅读器或任何其他 UI 自动化客户端 UI 元素有重要更改。 然后,屏幕阅读器可确定向用户通知此更改的方式和时间。 LiveSetting 属性还让屏幕阅读器知道了向用户通知 UI 更改的重要性。

      如何选择启用或弃用这些更改

      为了使应用程序从这些更改中获益,它必须在 .NET Framework 4.7.1 或更高版本上运行。 此应用程序可通过以下任何一种方式从这些更改中获益:

    • 面向 .NET Framework 4.7.1。 此为推荐方法。 对于面向 .NET Framework 4.7.1 或更高版本的 WPF 应用程序,这些辅助功能默认启用。

    • 通过向应用配置文件的 <runtime> 部分添加以下 AppContext 开关并将其设置为 false,可选择弃用旧版辅助功能行为,如下例所示。

      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <startup>
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
        </startup>
        <runtime>
          <!-- AppContextSwitchOverrides value attribute is in the form of 'key1=true/false;key2=true/false'  -->
          <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false" />
        </runtime>
      </configuration>
      

      如果应用程序面向 .NET Framework 4.7.1 或更高版本并希望保留旧版辅助功能行为,则它们可通过将此 AppContext 开关显式设置为 true 来选择启用旧版辅助功能。 有关 UI 自动化的概述,请参阅 UI 自动化概述

    • AutomationElementIdentifiers.LiveSettingProperty
    • AutomationElementIdentifiers.LiveRegionChangedEvent
    • System.Windows.Automation.AutomationLiveSetting
    • AutomationProperties.LiveSettingProperty
    • AutomationProperties.SetLiveSetting(DependencyObject, AutomationLiveSetting)
    • AutomationProperties.GetLiveSetting(DependencyObject)
    • AutomationPeer.GetLiveSettingCore()
    • 将 SelectionTextBrush 公共属性添加到 TextBox/PasswordBox 非装饰器选择功能

      在使用 TextBoxPasswordBox基于非装饰器的文本选择功能的 WPF 应用程序中,开发人员现在可以设置新添加的 SelectionTextBrush 属性,以便更改所选文本的呈现。 默认情况下,通过 HighlightTextBrushKey 更改此颜色。 如果未启用基于非修饰器的文本选择功能,则此属性不执行任何操作。

      启用基于非装饰器的文本选择功能后,可以使用 PasswordBox.SelectionTextBrushSelectionTextBrush 属性更改所选文本的外观。 可以使用 XAML 实现此操作:

      <TextBox SelectionBrush="Red" SelectionTextBrush="White"  SelectionOpacity="0.5"
      Foreground="Blue" CaretBrush="Blue">
      This is some text.
      </TextBox>
      
    • TextBoxBase.SelectionTextBrushProperty
    • TextBoxBase.SelectionTextBrush
    • System.Windows.Controls.TextBox
    • System.Windows.Controls.PasswordBox
    • HwndHost 现可在 DPI 更改期间正确重设子 HWND 的大小

      在 .NET Framework 4.7.2 和更低版本中,WPF 在预监测感知模式下运行时(例如,将应用程序从一个监视器移动到另一个监视器时),在 DPI 发生更改后,HwndHost 中托管的控件的大小不正确。 此修复程序可确保托管控件的大小适当。

      为了使应用程序能够从这些更改中受益,它必须在 .NET Framework 4.7.2 或更高版本上运行,并且必须选择加入此行为,方法是将应用配置文件的 <runtime> 部分中的以下 AppContext 开关设置为 false,如以下示例所示。

      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
      <startup>
      <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
      </startup>
      <runtime>
      <!-- AppContextSwitchOverrides value attribute is in the form of 'key1=true/false;key2=true/false  -->
      <AppContextSwitchOverrides value="Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=false" />
      </runtime>
      </configuration>
      

      现在,键盘焦点可在 WinForms/WPF 承载的多个层之间正确移动

      请考虑 WPF 应用程序,其承载的 WinForms 控件会反过来承载 WPF 控件。 如果该层的第一个或最后一个控件是 WPF System.Windows.Forms.Integration.ElementHost,那么用户可能不能按 Tab 离开 WinForms 层。 此更改修复了这个问题,现在,用户能按 Tab 离开 WinForms layer.Automated 应用程序。这些应用程序依赖于绝不转义 WinForms 层的焦点可能不再按预期工作。

      如果开发人员想要利用此更改,但面向 .NET 4.7.2 以下的框架版本,他可将下列一组 AppContext 标记设置为 false,从而启用更改。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false;Switch.UseLegacyAccessibilityFeatures.2=false"/>
      </runtime>
      </configuration>
      

      WPF 应用程序必须选择启用所有早期的可访问性改进,才能使用之后的改进。 换言之,必须同时设置 Switch.UseLegacyAccessibilityFeaturesSwitch.UseLegacyAccessibilityFeatures.2 开关。如果开发人员需要以前的功能,且面向 .NET 4.7.2 或更高版本,他可将以下 AppContext 标记设置为 false,从而禁用更改。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures.2=true"/>
      </runtime>
      </configuration>
      

      ImageSourceConverter.ConvertFrom 异常处理代码中的 NullReferenceException

      ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) 的异常处理代码中的错误导致引发不正确的 System.NullReferenceException 而不是预期的异常(System.IO.DirectoryNotFoundExceptionSystem.IO.FileNotFoundException)。 此更改更正了该错误,因此,该方法现在将引发正确的异常。

      默认情况下,所有面向 .NET Framework 4.6.2 和更低版本的应用程序都将继续引发 System.NullReferenceException 以确保兼容性。 面向 .NET Framework 4.7 和更高版本的开发人员应该能看到正确的异常。

      想要还原为在面向 .NET Framework 4.7 或更高版本时获取 System.NullReferenceException 的开发人员可将以下内容添加/合并到应用程序的 App.config 文件:

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Media.ImageSourceConverter.OverrideExceptionWithNullReferenceException=true"/>
      </runtime>
      </configuration>
      
    • ImageSourceConverter.ConvertFrom(ITypeDescriptorContext, CultureInfo, Object)
    • 选择器 SelectionChanged 事件和 SelectedValue 属性

      自 .NET Framework 4.7.1 起,在引发 SelectionChanged 事件之前,Selector 始终在选择更改时更新其 SelectedValue 属性值。 这使得 SelectedValue 属性与其他引发事件前更新的选择属性(SelectedItemSelectedIndex)相一致。

      在 .NET Framework 4.7 和更早版本中,大多情况下 SelectedValue 的更新发生在事件前,但是如果选择更改是由更改 SelectedValue 属性导致的,那么它发生在事件后。

      对于面向 .NET Framework 4.7.1 或更高版本的应用,可以在应用程序配置文件的 <runtime> 部分添加以下内容,从而选择弃用此更改并启用旧版行为:

      <runtime>
      <AppContextSwitchOverrides
      value="Switch.System.Windows.Controls.TabControl.SelectionPropertiesCanLagBehindSelectionChangedEvent=true" />
      </runtime>
      

      对于面向 .NET Framework 4.7 或更早版本,但在 .NET Framework 4.7.1 或更高版本上运行的应用,可以在应用程序配置文件的 <runtime> 部分中添加以下代码行,从而启用新的行为:

      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Controls.TabControl.SelectionPropertiesCanLagBehindSelectionChangedEvent=false" />
      </runtime>
      

      TabControl SelectionChanged 事件和 SelectedContent 属性

      从 .NET Framework 4.7.1 开始,当选择发生变化时,TabControl 在引发 SelectionChanged 事件之前更新其 SelectedContent 属性的值。而在 .NET Framework 4.7 和更早版本中,在事件发生之后才更新到 SelectedContent。

      对于面向 .NET Framework 4.7.1 或更高版本的应用,可以在应用程序配置文件的 <runtime> 部分添加以下内容,从而选择弃用此更改并启用旧版行为:

      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Controls.TabControl.SelectionPropertiesCanLagBehindSelectionChangedEvent=true" />
      </runtime>
      

      对于面向 .NET Framework 4.7 或更早版本,但在 .NET Framework 4.7.1 或更高版本上运行的应用,可以在应用程序配置文件的 <runtime> 部分中添加以下代码行,从而启用新的行为:

      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Controls.TabControl.SelectionPropertiesCanLagBehindSelectionChangedEvent=false" />
      </runtime>
      

      WPF PackageDigitalSignatureManager 现在的默认哈希算法是 SHA256

      System.IO.Packaging.PackageDigitalSignatureManager 提供与 WPF 包相关的数字签名功能。 在 .NET Framework 4.7 和更早版本中,包的签名部分使用的默认算法 (PackageDigitalSignatureManager.DefaultHashAlgorithm) 是 SHA1。 由于 SHA1 最近的安全问题,从 .NET Framework 4.7.1 起,此默认算法已更改为 SHA256。 此更改会影响所有包签名,包括 XPS 文档。

      面向 .NET Framework 4.7.1 以下框架版本并需要利用此更改的开发人员或者面向 .NET Framework 4.7.1 或更高版本并需要之前功能的开发人员可以正确设置以下 AppContext 标记。 值为 true 将导致 SHA1 作为默认算法使用;而 false 则导致 SHA256 作为默认算法使用。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.MS.Internal.UseSha1AsDefaultHashAlgorithmForDigitalSignatures=true"/>
      </runtime>
      </configuration>
      

      现在 WPF 标记编译器的默认哈希算法为 SHA256

      WPF 标记编译器为 XAML 标记文件提供编译服务。 在 .NET Framework 4.7.1 及更早版本中,用于校验和的默认哈希算法为 SHA1。 由于 SHA1 最近出现安全问题,从 .NET Framework 4.7.2 起,此默认算法已更改为 SHA256。 此更改会影响编译期间标记文件的所有校验和生成。

      如果开发人员面向 .NET Framework 4.7.2 或更高版本且想要还原到 SHA1 哈希行为,则必须设置以下 AppContext 标记。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Markup.DoNotUseSha256ForMarkupCompilerChecksumAlgorithm=true"/>
      </runtime>
      </configuration>
      

      如果开发人员面向 .NET 4.7.2 更低版本且想要利用 SHA256 哈希,则必须设置以下 AppContext 标记。 请注意,安装的 .NET Framework 必须是 4.7.2 或更高版本。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Markup.DoNotUseSha256ForMarkupCompilerChecksumAlgorithm=false
      </runtime>
      </configuration>
      

      不支持对具有非公共资源库的属性的双向数据绑定

      尝试将数据绑定到没有公共资源库的方案从未受支持。 从 .NET Framework 4.5.1 开始,此方案将引发 System.InvalidOperationException。 请注意,仅专门面向 .NET Framework 4.5.1 的应用会引发此新异常。 如果应用面向 .NET Framework 4.5,将允许该调用。 如果应用不面向特定 .NET Framework 版本,绑定将视为单向绑定。

      应更新应用以使用单向绑定,或公开公布属性的资源库。 或者,面向 .NET Framework 4.5 将使应用展示旧行为。

      WPF AppDomain 关闭处理现在可以调用 Dispatcher.Invoke 以清理弱事件

      在 .NET Framework 4.7.1 及更早的版本中,在 AppDomain 关闭期间,WPF 可能会在 .NET 终结器线程上创建 System.Windows.Threading.Dispatcher。 此问题已在 .NET Framework 4.7.2 和更高版本中得到修复,方法是使弱事件的清理能够感知线程。 因此,WPF 可能会调用 Dispatcher.Invoke 来完成清理过程。在某些应用程序中,终结器计时的这一更改可能在 AppDomain 或进程关闭期间导致异常。 这种情况常见于未在进程或 AppDomain 关闭之前正确关闭在工作线程上运行的调度程序的应用程序中。 此类应用程序应负责正确管理调度程序的生存期。

      在 .NET Framework 4.7.2 及更高版本中,开发人员可以禁用此修补程序以帮助缓解(但不能消除)由于清理更改而导致的计时问题。若要禁用清理中的更改,请使用以下 AppContext 标志。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.MS.Internal.DoNotInvokeInWeakEventTableShutdownListener=true"/>
      </runtime>
      </configuration>
      

      WPF 在主/从方案中显示 ADO 数据时更改主键

      假设你有 Order 类型的 ADO 项集合,其关系名为“OrderDetails”,通过主键“OrderID”将其关联到 Detail 类型的项集合。 在 WPF 应用程序中,你可以将列表控件绑定到给定顺序的详细信息:

      <ListBox ItemsSource="{Binding Path=OrderDetails}" >
      

      其中 DataContext 是一个 Order。 WPF 会获取 OrderDetails 属性的值 - 其 OrderID 与主项的 OrderID 匹配的所有 Detail 项的集合 D。 更改主项的主密钥 OrderID 时,会出现行为更改。 ADO 自动更改详细信息集合中每个受影响记录的 OrderID(即复制到集合 D 的信息)。 但 D 会发生什么?

    • 旧行为:清除集合 D。 主项不会发出属性 OrderDetails 的更改通知。 列表框将继续使用集合 D,现为空。
    • 新行为:集合 D 保持不变。 其中每一项都将发出 OrderID 属性的更改通知。 列表框将持续使用集合 D,并显示新 OrderID 的详细信息。 WPF 通过不同的方式创建集合 D 来实现新行为:通过调用 ADO 方法 DataRowView.CreateChildView(DataRelation, Boolean),并将 followParent 参数设置为 true
    • 应用通过使用以下 AppContext 开关获取新行为。

      <configuration>
        <runtime>
          <AppContextSwitchOverrides value="Switch.System.Windows.Data.DoNotUseFollowParentWhenBindingToADODataRelation=false"/>
        </runtime>
      </configuration>
      

      对于面向 .NET 4.7.1 或更低版本的应用,开关默认为 true(旧行为),而对于面向 .NET 4.7.2 或更高版本的应用,开关默认为 false(新行为)。

      RadioButton 和 CheckBox 的 WPF FocusVisual 现可在控件无内容时正确显示

      在 .NET Framework 4.7.1 和更早版本中,WPF System.Windows.Controls.CheckBoxSystem.Windows.Controls.RadioButton 不一致且在经典和高对比度主题中具有不正确的焦点视觉对象。 控件没有内容集时会出现这些问题。 这会使得主题间的转换变得混乱且难以看到焦点视觉对象。 现在,在 .NET Framework 4.7.2 中,主题间的这些视觉对象更加一致,并且在经典和高对比度主题中更轻松可见。

      如果开发人员面向 .NET Framework 4.7.2,但要还原到 .NET 4.7.1 行为,则需要设置以下 AppContext 标记。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures.2=true;"/>
      </runtime>
      </configuration>
      

      如果开发人员面向 .NET 4.7.2 以下的框架版本,但想要利用此更改,则必须设置以下 AppContext 标记。请注意,必须正确设置所有标记,并且安装的 .NET Framework 版本必须是 4.7.2 或更高版本。WPF 应用程序需选择启用所有的早期辅助功能改进,才能获取最新改进。 若要执行此操作,请确保将“Switch.UseLegacyAccessibilityFeatures”和“Switch.UseLegacyAccessibilityFeatures.2”这两个 AppContext 开关设置为 false。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false;Switch.UseLegacyAccessibilityFeatures.2=false;"/>
      </runtime>
      </configuration>
      

      WPF 网格向 -列分配空间

      从 .NET Framework 4.7 开始,WPF 替换了 Grid 用于向 *-列分配空间的算法。 这在以下许多情况下会更改分配给 *-列的实际宽度:

    • 当一个或多个 *-列的最小或最大宽度替代相应列的按比例分配空间时。 (最小宽度可以派生自 MinWidth 显式声明,也可以派生自从列内容中获取的隐式最小值。只能通过 MaxWidth 声明显式定义最大宽度。)

    • 当一个或多个 *-列声明极大 *-权重时(即大于 10^298)。

    • 当 *-权重明显不同,遇到了浮点不稳定问题(溢出、下溢、精度损失)时。

    • 当布局圆化处理已启用且有效显示 DPI 足够高时。 在前两种情况下,新旧算法生成的宽度明显不同;在最后一种情况下,新旧算法生成的宽度最多相差一或两个像素。

      新算法修复了旧算法中的以下多处 bug:

    • 向列分配的总空间可能会超过网格宽度。 当向比例份额小于其大小下限的列分配空间时,可能会出现这种问题。 算法会分配大小下限对应的空间,这将减少其他列的可用空间。 如果没有可分配空间的 *-列剩余,分配的总空间可能会过大。

    • 向列分配的总空间可能会占不满网格宽度。 这是第 1 个问题的对偶问题,当向比例份额大于其大小上限的列分配空间,没有剩余的 *-列来收紧空间时,可能会出现这种问题。

    • 可能会向两个 *-列分配与其 *-权重不成比例的空间。 这是第 1 个/第 2 个问题造成的较为温和的影响,当依序向 *-列 A、B 和 C 分配空间,但 B 列的比例份额与约束下限(或上限)冲突时,可能会出现这种问题。 同样,这会更改 C 列的可用空间,它将比 A 列获得更少(或更多)的按比例分配空间。

    • 权重极大 (> 10^298) 的列全都被视为具有权重 10^298。 这些列(以及权重略小的列)之间的比例差异将不会生效。

    • 无法正确处理权重无穷大的列。 [实际上,不能设置无穷大的权重,但这是一项人为限制。 空间分配代码是在努力处理这样的列,但处理得并不好。]

    • 在避免溢出、下溢、精度损失和类似浮点问题时,存在一些小问题。

    • 在 DPI 足够高的情况下,无法正确调整布局的圆化处理。 新算法生成符合以下条件的结果:

      A. 分配给 *-列的实际宽度永远不会小于其最小宽度,也不会大于其最大宽度。
      B. 对于没有分配最小或最大宽度的每个 -列,向其分配与其 -权重成比例的宽度。确切地讲,如果分别使用宽度 x 和 y 声明两个列,且没有向这两个列分配最小或最大宽度,那么将按同一比例向这两个列分配实际宽度 v 和 w:v / w == x / y。
      C. 分配给“成比例的”*-列的总宽度等于分配给受约束列(向其分配了最小或最大宽度的固定、自动和 *-列)后剩余的可用空间。 此空间可能为零(例如,当最小宽度的总和超过了网格的可用宽度时)。
      D. 所有这些语句都是针对“理想”布局进行解释的。 当布局圆化处理有效时,实际宽度与理想宽度可能会相差一个像素。
      旧算法遵循 (A),但在上述情况下无法遵守其他条件。

      本文中有关列和宽度的所有内容也适用于行和高度。

      默认情况下,面向 .NET Framework 4.7 和更高版本的应用将使用新算法,而面向 .NET Framework 4.6.2 或更早版本的应用程序将使用旧算法。

      要替代默认情况,请使用以下配置设置:

      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Controls.Grid.StarDefinitionsCanExceedAvailableSpace=true" />
      </runtime>
      

      值为 true 表示选择旧算法,值为 false 表示选择新算法。

      由于这种修改往往会消除高 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" />'.
      

      基于 WPF 指针的触控堆栈

      此次更改后,可启用基于可选 WM_POINTER 的 WPF 触控/触笔堆栈。 没有显式启动此功能的开发人员应该看不到 WPF 触控/触笔行为的更改。基于 WPF 触控/触笔堆栈的可选 WM_POINTER 当前存在的已知问题:

    • 不支持实时墨迹书写。
    • 尽管墨迹书写和触笔插件仍可运行,但它们是在 UI 线程上进行处理,这可能会导致性能变得糟糕。
    • 从触控/触笔事件提升到鼠标事件方面的更改导致行为发生变化
    • 控制行为可能不同
    • 拖/放行为无法正确显示触控输入反馈
    • 这不会影响触笔输入
    • 无法再通过触控/触笔事件启动拖/放行为
    • 这可能会导致应用程序停止响应,直到检测到鼠标输入。
    • 相反,开发者应通过鼠标事件启动拖放行为。
    • 要启用此堆栈的开发者可以在应用程序的 App.config 文件中添加/合并下面的代码:

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true"/>
      </runtime>
      </configuration>
      

      删除它或将该值设为 false 将关闭此可选堆栈。请注意,此堆栈仅在 Windows 10 创意者更新以及更高版本上可用。

      WPF TextBox/PasswordBox 文本选择不遵循系统颜色

      在 .NET Framework 4.7.1 和更早版本中,WPF System.Windows.Controls.TextBoxSystem.Windows.Controls.PasswordBox 只能在装饰器层呈现文本选择。 在某些系统主题中,这会遮蔽文本,使其难以阅读。 在 .NET Framework 4.7.2 及更高版本中,开发人员可选择启用基于非装饰器的选择呈现方案,从而缓解此问题。

      开发人员若要利用此更改,必须正确设置以下 AppContext 标记。 若要利用此功能,已安装的 .NET Framework 必须是 4.7.2 或更高版本。若要启用基于非装饰器的选择,请使用以下 AppContext 标记。

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Windows.Controls.Text.UseAdornerForTextboxSelectionRendering=false"/>
      </runtime>
      </configuration>
      

      Windows Workflow Foundation (WF) 工作流设计器中的辅助功能改进

      Windows Workflow Foundation (WF) 工作流设计器正在改进辅助功能技术的工作原理。 这些改进包括以下更改:

    • 某些控件中 Tab 键顺序更改为从左到右以及从上到下:
    • 设置 InitializeCorrelation 活动相关数据的初始化相关窗口
    • ReceiveSendSendReplyReceiveReply 活动的内容定义窗口
    • 通过键盘可以使用更多功能:
    • 编辑活动的属性时,属性组在第一次聚焦时可以通过键盘折叠。
    • 警告图标现在可以通过键盘访问。
    • “属性”窗口的“更多属性”按钮现在可以通过键盘访问。
    • 键盘用户现在可以访问工作流设计器“自变量和变量”窗格的标题项。
    • 提升了聚焦项的可见性,例如当:
    • 将行添加到工作流设计器和活动设计器使用的数据网格。
    • ReceiveReplySendReply 活动中按 Tab 键切换字段。
    • 设置变量或自变量的默认值
    • 屏幕读取器现在可以正确识别:
    • 工作流设计器中设置的断点。
    • FlowSwitch<T>FlowDecisionCorrelationScope 活动。
    • Receive 活动的内容。
    • InvokeMethod 活动的目标类型。
    • TryCatch 活动中的“异常”组合框和“最终”部分。
    • 消息传递活动(ReceiveSendSendReplyReceiveReply)中的“消息类型”组合框、“添加相关初始化表达式”窗口中的拆分器、“内容定义”窗口和“CorrelatesOn 定义”窗口。
    • 状态机转换和转换目标。
    • FlowDecision 活动上的注释和连接器。
    • 活动的上下文(右键单击)菜单。
    • 属性值编辑器、“清除搜索”按钮、“按类别”和“按字母顺序”排序按钮以及属性网格中的“表达式编辑器”对话框。
    • 工作流设计器中的缩放百分比。
    • ParallelPick 活动中的分隔符。
    • InvokeDelegate 活动。
    • 字典活动(Microsoft.Activities.AddToDictionary<TKey,TValue>Microsoft.Activities.RemoveFromDictionary<TKey,TValue> 等)的“选择类型”窗口。
    • “浏览和选择 .NET 类型”窗口。
    • 工作流设计器中的痕迹导航。
    • 选择高对比度主题的用户将看到工作流设计器及其控件可见性的许多改进,例如元素间更好的对比度和焦点元素更明显的选择框。
    • 如果你的应用程序有重新承载的工作流设计器,那么该应用程序可以通过执行其中任一操作从这些更改中受益:

    • 重新编译应用程序以面向 .NET Framework 4.7.1。 这些辅助功能更改在默认情况下启用。
    • 如果应用程序面向 .NET Framework 4.7 或更早版本,但在 .NET Framework 4.7.1 上运行,则可以通过将以下 AppContext switch 添加到 app.config 文件的 <runtime> 部分并将其设为 false(如以下示例所示),选择弃用这些旧版辅助功能行为。
    • <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <startup>
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
        </startup>
        <runtime>
          <!-- AppContextSwitchOverrides value attribute is in the form of 'key1=true/false;key2=true/false  -->
          <AppContextSwitchOverrides value="Switch.UseLegacyAccessibilityFeatures=false" />
        </runtime>
      </configuration>
      

      面向 .NET Framework 4.7.1 或更高版本并希望保留旧版辅助功能行为的应用程序,可通过将此 AppContext 开关显式设置为 true 来选择启用旧版辅助功能。

      避免 IWorkflowInstanceManagement.TransactedCancel 和 IWorkflowInstanceManagement.TransactedTerminate 无限递归

      在某些情况下,使用 IWorkflowInstanceManagement.TransactedCancelIWorkflowInstanceManagement.TransactedTerminate API 取消或终止工作流服务实例时,由于 Workflow 运行时尝试将服务实例永久保存为处理请求的一部分时出现无限递归,工作流实例可能会遇到堆栈溢出情况。 如果工作流实例处于等待另一项服务的其他未完成 WCF 请求完成的状态,则会出现此问题。 TransactedCancelTransactedTerminate 操作会创建排队等待工作流服务实例的工作项。 这些工作项目不会作为 TransactedCancel/TransactedTerminate 请求处理的一部分执行。 由于工作流服务实例正忙于等待其他未完成 WCF 请求的完成,所以创建的工作项继续排队。 TransactedCancel/TransactedTerminate 操作完成且控件返回到客户端。 与 TransactedCancel/TransactedTerminate 操作相关的事务尝试提交时,它需保存工作流服务实例状态。 但是,由于该实例有未完成的 WCF 请求,所以工作流运行时无法保存工作流服务实例,并且无限递归循环会导致堆栈溢出。因为 TransactedCancelTransactedTerminate 仅在内存中创建工作项,所以不影响事务存在这一事实。 事务回滚不会放弃工作项。为了解决此问题,自 .NET Framework 4.7.2 起,我们引入了 AppSetting,可将其添加到工作流服务的 web.config/app.config,使其忽略 TransactedCancelTransactedTerminate 的事务。 这样,不必等待工作流实例保留即可提交事务。 此功能的 AppSetting 名为 microsoft:WorkflowServices:IgnoreTransactionsForTransactedCancelAndTransactedTerminatetrue 值表示应忽略事务,从而避免堆栈溢出。 此 AppSetting 的默认值是 false,因此不影响现有工作流服务实例。

      如果正在使用 AppFabric 或另一个 IWorkflowInstanceManagement 客户端,并且在尝试取消或终止工作流实例时遇到工作流服务实例中堆栈溢出问题,那么可以将以下内容添加到工作流服务 web.config/app.config 文件的 <appSettings> 部分:

      <add key="microsoft:WorkflowServices:IgnoreTransactionsForTransactedCancelAndTransactedTerminate" value="true"/>
      

      如果没有遇到问题,则不需要执行此操作。

      新的(不明确的)Dispatcher.Invoke 重载可能导致不同的行为

      .NET Framework 4.5 将新重载添加到包括 Action 类型参数的 Dispatcher.Invoke。 在重新编译现有代码时,编译器可能将对具有 Delegate 参数的 Dispatcher.Invoke 方法的调用解析为对具有 Action 参数的 Dispatcher.Invoke 方法的调用。 如果将对具有 Delegate 参数的 Dispatcher.Invoke 重载的调用解析为对具有 Action 参数的 Dispatcher.Invoke 重载的调用,可能出现以下行为差异:

    • 如果出现异常,则不引发 UnhandledExceptionFilterUnhandledException 事件。 相反,通过 System.Threading.Tasks.TaskScheduler.UnobservedTaskException 事件处理异常。
    • 对某些成员(如 Result)的调用会受阻,直到操作完成。
    • 若要避免出现多义性(以及异常处理或阻止行为中可能出现的差异),调用 Dispatcher.Invoke 的代码可传递空 object[] 作为 Invoke 调用的第二个参数,确保解析为 .NET Framework 4.0 方法重载。

    • Dispatcher.Invoke(Delegate, Object[])
    • Dispatcher.Invoke(Delegate, TimeSpan, Object[])
    • Dispatcher.Invoke(Delegate, TimeSpan, DispatcherPriority, Object[])
    • Dispatcher.Invoke(Delegate, DispatcherPriority, Object[])
    • 某些工作流拖放 API 已过时

      此工作流拖放 API 已过时,如果针对 4.5 重新生成应用,将引发编译器警告。

      应改用支持包含多个对象的操作的新 System.Activities.Presentation.DragDropHelper API。 或者,可以禁止显示生成警告,也可以使用较早的编译器避免出现此类警告。 API 仍受支持。

    • DragDropHelper.DoDragMove(WorkflowViewElement, Point)
    • DragDropHelper.GetCompositeView(DragEventArgs)
    • DragDropHelper.GetDraggedModelItem(DragEventArgs)
    • DragDropHelper.GetDroppedObject(DependencyObject, DragEventArgs, EditingContext)
    • WorkFlow 3.0 类型已过时

      Windows Workflow Foundation (WWF) 3.0 API(来自于 System.Workflow 命名空间)现已过时。

      应改用新的 WWF 4.0 API(在 System.Activities 中)。 可在此处找到使用新 API 的示例,此处还提供更深入的指导。 或者,由于仍然支持 WWF 3.0 API,因此可能会使用它们,通过禁止显示生成时警告或使用较旧的编译器可以避免出现该警告。

      工作流校验和已从 MD5 更改为 SHA1

      为支持使用 Visual Studio 进行调试,工作流运行时使用哈希算法为工作流实例生成校验和。 在 .NET Framework 4.6.2 和早期版本中,工作流校验和哈希使用 MD5 算法,这会在启用 FIPS 的系统上导致问题。 从 .NET Framework 4.7 开始,算法为 SHA1。 如果代码保留了这些校验和,它们将是不兼容的。

      如果代码由于校验和失败而无法加载工作流实例,请尝试将 AppContext 开关“Switch.System.Activities.UseMD5ForWFDebugger”设置为 true。在代码中:

      System.AppContext.SetSwitch("Switch.System.Activities.UseMD5ForWFDebugger", true);
      

      或在配置中:

      <configuration>
        <runtime>
          <AppContextSwitchOverrides value="Switch.System.Activities.UseMD5ForWFDebugger=true" />
        </runtime>
      </configuration>
      

      符号的工作流 XAML 校验和从 SHA1 更改为 SHA256

      为支持使用 Visual Studio 进行调试,工作流运行时使用哈希算法生成工作流 XAML 文件的校验和。 在 .NET Framework 4.6.2 和早期版本中,工作流校验和哈希使用 MD5 算法,这会在启用 FIPS 的系统上导致问题。 从 .NET Framework 4.7 开始,默认算法已更改为 SHA1。 从 .NET Framework 4.8 开始,默认算法已更改为 SHA256。

      如果由于校验和失败,代码无法加载工作流实例或找不到相应符号,请尝试将 AppContext 开关“Switch.System.Activities.UseSHA1HashForDebuggerSymbols”设置为 true。 在代码中:

      System.AppContext.SetSwitch("Switch.System.Activities.UseSHA1HashForDebuggerSymbols", true);
      

      或在配置中:

      <configuration>
        <runtime>
          <AppContextSwitchOverrides value="Switch.System.Activities.UseSHA1HashForDebuggerSymbols=true" />
        </runtime>
      </configuration>
      

      工作流 XOML 定义和 SqlTrackingService 缓存密钥已从 MD5 更改为 SHA256

      工作流运行时保存 XOML 中定义的工作流定义的缓存。 SqlTrackingService 还保留按字符串键入的缓存。 由包含校验和哈希值的值键入这些缓存。 在 .NET Framework 4.7.2 和早期版本中,该校验和哈希使用 MD5 算法,这会在启用 FIPS 的系统上导致问题。 从 .NET Framework 4.8 开始,使用的算法为 SHA256。由于每次工作流运行时和 SqlTrackingService 启动时都会重新计算值,因此进行此更改后不会出现兼容性问题。 但是,我们提供了可以让客户恢复使用旧版哈希算法的例外做法(如有必要)。

      如果此更改在执行工作流时出现问题,请尝试设置一个或两个 AppContext 开关:

    • 将“Switch.System.Workflow.Runtime.UseLegacyHashForWorkflowDefinitionDispenserCacheKey”设为 true。
    • 将“Switch.System.Workflow.Runtime.UseLegacyHashForSqlTrackingCacheKey”设为 true。 在代码中:
    • System.AppContext.SetSwitch("Switch.System.Workflow.Runtime.UseLegacyHashForWorkflowDefinitionDispenserCacheKey", true);
      System.AppContext.SetSwitch("Switch.System.Workflow.Runtime.UseLegacyHashForSqlTrackingCacheKey", true);
      

      或者在配置文件中(这需要在创建 WorkflowRuntime 对象的应用程序的配置文件中):

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Workflow.Runtime.UseLegacyHashForWorkflowDefinitionDispenserCacheKey=true" />
      <AppContextSwitchOverrides value="Switch.System.Workflow.Runtime.UseLegacyHashForSqlTrackingCacheKeytrue" />
      </runtime>
      </configuration>
      

      工作流 XOML 文件校验和已从 MD5 更改为 SHA256

      为了支持使用 Visual Studio 调试基于 XOML 的工作流,当生成包含 XOML 文件的工作流项目时,系统会将 XOML 文件内容的校验和作为 WorkflowMarkupSourceAttribute.MD5Digest 值包含在生成的代码中。 在 .NET Framework 4.7.2 和早期版本中,该校验和哈希使用 MD5 算法,这会在启用 FIPS 的系统上导致问题。 从 .NET Framework 4.8 开始,采用的算法为 SHA256。 为了与 WorkflowMarkupSourceAttribute.MD5Digest 兼容,只使用生成的校验和的前 16 个字节。这可能会导致调试过程中出现问题。 可能需要重新生成项目。

      如果重新生成项目没有解决问题,请尝试在代码中将 AppContext 开关 Switch.System.Workflow.ComponentModel.UseLegacyHashForXomlFileChecksum 设置为 true:

      System.AppContext.SetSwitch("Switch.System.Workflow.ComponentModel.UseLegacyHashForXomlFileChecksum", true);
      

      或者在配置文件中设置(需要位于正在使用的 MSBuild.exe 的 MSBuild.exe.config 中):

      <configuration>
      <runtime>
      <AppContextSwitchOverrides value="Switch.System.Workflow.ComponentModel.UseLegacyHashForXomlFileChecksum=true" />
      </runtime>
      </configuration>
      

      XML 架构验证更为严格

      在 .NET Framework 4.5 中,XML 架构验证更为严格。 如果使用 xsd:anyURI 来验证 URL(如 mailto 协议),则当 URL 中有空格时,验证将失败。 在 .NET Framework 的早期版本中,验证将成功。 此更改仅影响面向 .NET Framework 4.5 的应用程序。

      如果需要更宽松的 .NET Framework 4.0 验证,该验证应用程序可以面向版本 4.0 的 .NET Framework。 但是,重定向到 .NET Framework 4.5 时,应执行代码评审,确保无效的 URI(包含空格)不会作为 anyURI 数据类型的属性值。

      XmlWriter 引发无效的代理项对

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

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

    • XmlWriter.WriteAttributeString(String, String)
    • XmlWriter.WriteAttributeString(String, String, String)
    • XmlWriter.WriteAttributeString(String, String, String, String)
    • XmlWriter.WriteAttributeStringAsync(String, String, String, String)
    • XmlWriter.WriteCData(String)
    • XmlWriter.WriteCDataAsync(String)
    • XmlWriter.WriteChars(Char[], Int32, Int32)
    • XmlWriter.WriteCharsAsync(Char[], Int32, Int32)
    • XmlWriter.WriteComment(String)
    • XmlWriter.WriteCommentAsync(String)
    • XmlWriter.WriteEntityRef(String)
    • XmlWriter.WriteEntityRefAsync(String)
    • XmlWriter.WriteRaw(Char[], Int32, Int32)
    • XmlWriter.WriteProcessingInstruction(String, String)
    • XmlWriter.WriteProcessingInstructionAsync(String, String)
    • XmlWriter.WriteRaw(String)
    • XmlWriter.WriteRawAsync(Char[], Int32, Int32)
    • XmlWriter.WriteRawAsync(String)
    • XmlWriter.WriteString(String)
    • XmlWriter.WriteStringAsync(String)
    • XmlWriter.WriteSurrogateCharEntity(Char, Char)
    • XmlWriter.WriteSurrogateCharEntityAsync(Char, Char)
    • XmlWriter.WriteValue(String)
    • 如果使用复合密钥并且一个密钥为空,XSD 架构验证现在可正确检测是否违反唯一约束

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

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

  •