System.Drawing.Common が Windows でしかサポートされない

System.Drawing.Common NuGet パッケージは、Windows 固有のライブラリとして属性付けされるようになりました。 Windows 以外のオペレーティング システム用にコンパイルすると、コンパイル時にプラットフォーム アナライザーから警告が生成されます。

Windows 以外のオペレーティング システムでは、ランタイム構成スイッチを設定しない限り、PlatformNotSupportedException を内部例外として TypeInitializationException の例外がスローされます。

以前の動作

.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 には、画像処理、テキスト レンダリング (cairopango など)、他のネイティブ ライブラリなど、多数の外部依存関係もあります。 これらの依存関係があるため、コンポーネントの保守とリリースがさらに困難になっています。 Mono クロスプラットフォーム実装が含まれるようになって以来、多くの問題を libgdiplus にリダイレクトしてきましたが、修正されたことはありませんでした。 一方、他の採用した外部依存関係 (icuopenssl など) は高品質のライブラリです。 libgdiplus の機能セットと品質が他の .NET スタックと同等になるようにするのは現実的ではありません。

NuGet パッケージの分析から、System.Drawing.Common は、主に QR コード ジェネレーターやテキスト レンダリングなどの画像処理のために、クロスプラットフォームで使用されていることがわかりました。 クロスプラットフォームのグラフィック サポートは不完全であるため、グラフィックの使用量が多いことを認識していませんでした。 Windows 以外の環境での System.Drawing.Common の使用は、通常、SkiaSharp で十分にサポートされています。

System.Drawing.Common は、Windows フォームと GDI+ のコンテキストでのみ進化し続ける予定です。

これらの API をクロスプラットフォーム アプリで使用するには、次のいずれかのライブラリに移行してください。

または、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 以外のバグは修正されなくなります。
  • このスイッチは .NET 6 でのみ使用でき、.NET 7 では削除されました。

影響を受ける API

System.Drawing 名前空間:

System.Drawing.Drawing2D 名前空間:

System.Drawing.Imaging 名前空間:

System.Drawing.Printing 名前空間:

System.Drawing.Text 名前空間:

関連項目