仅在 Windows 上支持 System.Drawing.Common
System.Drawing.Common NuGet 包现在被归为 Windows 特定的库。 在为非 Windows 操作系统编译时,平台分析器会在编译时发出警告。
在非 Windows 操作系统上,除非设置了运行时配置开关,否则将引发 TypeInitializationException 异常,其中 PlatformNotSupportedException 作为内部异常。
旧行为
在 .NET 6 之前,使用 System.Drawing.Common 包不会产生任何编译时警告,也不会引发任何运行时异常。
新行为
从 .NET 6 开始,当为非 Windows 操作系统编译引用代码时,平台分析器会发出编译时警告。 此外,除非设置了配置选项,否则将引发以下运行时异常:
System.TypeInitializationException : The type initializer for 'Gdip' threw an exception.
---- System.PlatformNotSupportedException : System.Drawing.Common is not supported on non-Windows platforms. See https://aka.ms/systemdrawingnonwindows for more information.
Stack Trace:
at System.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromFile(String filename, IntPtr& bitmap)
/_/src/libraries/System.Drawing.Common/src/System/Drawing/Bitmap.cs(42,0): at System.Drawing.Bitmap..ctor(String filename, Boolean useIcm)
/_/src/libraries/System.Drawing.Common/src/System/Drawing/Bitmap.cs(25,0): at System.Drawing.Bitmap..ctor(String filename)
/_/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs(270,0): at System.Resources.Tests.ResourceManagerTests.EnglishImageResourceData()+MoveNext()
/_/src/libraries/System.Linq/src/System/Linq/Select.cs(136,0): at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
----- Inner Stack Trace -----
/_/src/libraries/System.Drawing.Common/src/System/Drawing/LibraryResolver.cs(31,0): at System.Drawing.LibraryResolver.EnsureRegistered()
/_/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Unix.cs(65,0): at System.Drawing.SafeNativeMethods.Gdip.PlatformInitialize()
/_/src/libraries/System.Drawing.Common/src/System/Drawing/Gdiplus.cs(27,0): at System.Drawing.SafeNativeMethods.Gdip..cctor()
引入的版本
.NET 6
中断性变更的类型
更改原因
由于 System.Drawing.Common
被设计为 Windows 技术的精简包装器,因此其跨平台实现欠佳。
libgdiplus
是本机端 System.Drawing.Common
跨平台实现的主要提供程序。 libgdiplus
实际上是对 System.Drawing.Common
所依赖的 Windows 部分的重新实现。 该实现使 libgdiplus
成为一个重要的组件。 它大约有 30,000 行 C 代码,大部分未经测试,而且缺少很多功能。 libgdiplus
还具有许多用于图像处理和文本呈现的外部依赖项,例如 cairo
、pango
和其他本机库。 这些依赖项使得维护和交付组件更具挑战性。 自从包含 Mono 跨平台实现以来,我们已将许多从未得到修复的问题重定向到 libgdiplus
。 相比之下,我们采用的其他外部依赖项,例如 icu
或 openssl
,都是高质量的库。 使 libgdiplus
的功能集和质量与 .NET 堆栈的其余部分相媲美是不可行的。
通过对 NuGet 包的分析,我们观察到 System.Drawing.Common
主要用于跨平台的图像处理,例如 QR 代码生成器和文本呈现。 由于我们的跨平台图形支持不完整,我们还没有注意到大量的图形使用。 System.Drawing.Common
在非 Windows 环境中的使用通常得到 SkiaSharp 和 ImageSharp 的良好支持。
System.Drawing.Common
将仅在 Windows 窗体和 GDI+ 的上下文中继续演变。
建议的操作
若要将这些 API 用于跨平台应用,请迁移到以下库之一:
- SkiaSharp
- ImageSharp(分层许可证)
- Aspose.Drawing(商业许可证)
- Microsoft.Maui.Graphics
或者,可通过将 runtimeconfig.json 文件中的 System.Drawing.EnableUnixSupport
运行时配置开关设置为 true
来启用对 .NET 6 中非 Windows 平台的支持。
runtimeconfig.template.json 模板文件:
{
"configProperties": {
"System.Drawing.EnableUnixSupport": true
}
}
[appname].runtimeconfig.json 输出文件:
{
"runtimeOptions": {
"configProperties": {
"System.Drawing.EnableUnixSupport": true
}
}
}
注意
- 添加此配置开关是为了让严重依赖此包的跨平台应用有时间迁移到更新式的库。 但是,不会修复非 Windows bug。
- 此开关仅在 .NET 6 中可用,在 .NET 7 中已删除。 有关详细信息,请参阅已删除 System.Drawing.Common 配置开关。
受影响的 API
System.Drawing 命名空间:
- Bitmap
- Brush
- Brushes
- BufferedGraphics
- BufferedGraphicsContext
- Font
- FontFamily
- FontConverter
- Graphics
- Icon
- IconConverter
- Image
- ImageAnimator
- Pen
- Pens
- Region
- SolidBrush
- StringFormat
- SystemBrushes
- SystemFonts
- SystemIcons
- SystemPens
- TextureBrush
System.Drawing.Drawing2D 命名空间:
- AdjustableArrowCap
- CustomLineCap
- GraphicsPath
- GraphicsPathIterator
- GraphicsState
- HatchBrush
- LinearGradientBrush
- Matrix
- PathGradientBrush
System.Drawing.Imaging 命名空间:
- Encoder
- EncoderParameter
- EncoderParameters
- ImageAttributes
- ImageCodecInfo
- ImageFormat
- Metafile
- MetafileHeader
- PlayRecordCallback
System.Drawing.Printing 命名空间:
- PageSettings
- PreviewPageInfo
- PrintController
- PrintDocument
- PrinterSettings
- PrintEventArgs
- PrintEventHandler
- PrintPageEventArgs
- PrintPageEventHandler
System.Drawing.Text 命名空间: