Поделиться через


System.Drawing.Common поддерживается только в Windows

Пакет NuGet System.Drawing.Common теперь считается библиотекой для 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 — это фактически повторная реализация частей Windows, от которых зависит System.Drawing.Common. Эта реализация делает 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 Forms и GDI+.

Чтобы использовать эти API для кроссплатформенных приложений, выполните миграцию в одну из следующих библиотек:

Кроме того, можно включить поддержку платформ, отличных от Windows, в .NET 6, задав System.Drawing.EnableUnixSupport параметр true конфигурации среды выполнения в файле runtimeconfig.json .

файл шаблона runtimeconfig.template.json:

{
   "configProperties": {
      "System.Drawing.EnableUnixSupport": true
   }
}

[appname].runtimeconfig.json выходной файл:

{
   "runtimeOptions": {
      "configProperties": {
         "System.Drawing.EnableUnixSupport": true
      }
   }
}

Примечание.

  • Этот параметр конфигурации был добавлен, чтобы дать время перевести кроссплатформенные приложения, которые сильно зависят от этого пакета, на более современные библиотеки. Но мы не будем устранять ошибки, которые не связанны с Windows.
  • Этот параметр доступен только в .NET 6 и удален в .NET 7. Дополнительные сведения см. в разделе "Удаленный параметр конфигурации System.Drawing.Common".

Затронутые API

Пространство имен System.Drawing:

Пространство имен System.Drawing.Drawing2D:

Пространство имен System.Drawing.Imaging:

Пространство имен System.Drawing.Printing:

Пространство имен System.Drawing.Text:

См. также