Windows Container之.NET Core找不到gdiplus.dll解決方案

Windows Container之.NET Core找不到gdiplus.dll解決方案

同事回報,有一支 API 轉移至 Windows Container 之後,特定 Action 會產生 HTTP 500 錯誤,查詢容器日誌快速定位到問題:

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HLHTEASOTJDP", Request id "0HLHTEASOTJDP:00000002": An unhandled exception was thrown by the application.
System.TypeInitializationException: The type initializer for 'ClosedXML.Excel.XLHelper' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Gdip' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'gdiplus.dll': The specified module could not be found.
   at System.Runtime.InteropServices.FunctionWrapper`1.get_Delegate()
   at System.Drawing.SafeNativeMethods.Gdip.GdiplusStartup(IntPtr& token, StartupInput& input, StartupOutput& output)
   at System.Drawing.SafeNativeMethods.Gdip..cctor()
   --- End of inner exception stack trace ---
   at System.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0(Int32 width, Int32 height, Int32 stride, Int32 format, HandleRef scan0, IntPtr& bitmap)
   at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
   at ClosedXML.Excel.XLHelper..cctor()
   --- End of inner exception stack trace ---

原因是匯出的 Excel 的 ClosedXML 元件的問題,重點在:「System.DllNotFoundException: Unable to load DLL 'gdiplus.dll': The specified module could not be found.」但奇怪的的是在我們電腦是好的,進容器後就不正常

Unable to load DLL 'gdiplus.dll' 為關鍵字查詢,能找到一大堆關於 .NET Core 與 Linux 相關的討論串,大部分提供的解法都是執行 apt-get install -y libgdiplus or brew install mono-libgdiplus 把 gdiplus.dll 裝上去就能解決了。

但我是 Windows Container 呀~~~

找了好久才了解,原來問題是出在 Nano Server Based Image 並未包含 gdiplus.dll,所以當我們以 microsoft/dotnet:2.1-aspnetcore-runtime 為 Based Image 來封裝的容器時,就會出現以上錯誤。知道原因後,我想,是否能模仿 Linux 的作法,把 gdiplus.dll 包到專案裡。

NuGet for System.Drawing

在 NuGet 上有二個 Microsoft 放上去的 System.Drawing 組件。測試結果只是更新專案組件到較新版本的 System.Drawing,但關鍵的找不到 gdiplus.dll 問題還是沒解。

自行編譯 gdiplus.dll

有人提到,可以試試用 Mono libgdilus。好吧,人生第一次裝 C++ 相關工具:

PS C:\vcpkg> .\bootstrap-vcpkg.bat
Could not find MSBuild version with C++ support. VS2015 or VS2017 (with C++) needs to be installed.
位於 C:\Users\BruceChen\Downloads\vcpkg\scripts\bootstrap.ps1:185 字元:5
+     throw "Could not find MSBuild version with C++ support. VS2015 or ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Could not find ...o be installed.:String) [], RuntimeException
    + FullyQualifiedErrorId : Could not find MSBuild version with C++ support. VS2015 or VS2017 (with C++) needs to be installed.

Visual Studio 也要裝相關 C++ 與對應的 Windows SDK 才行。經過漫長下載與安裝,然後開始面對一堆 Build fail ... 這不是我想要的呀。處理 C++ 的 Build fail 這不是我專長...我放棄了。

在我們電腦是好的?

對了,為何在我們電腦是好的?前面說過,這個 gdiplus.dll 只有在 Nano Server Based Image 被移除了,那麼意思是 Server Core Base Image 還存在?

Try it!

目前微軟官方 https://hub.docker.com/r/microsoft/dotnet/ 為了效能與縮減大小都是以 Nano Server 為基礎來製作 Images。沒有 Server Core 的版本,沒有,那就自己來做一個吧。

讀者可以使用我做好的 docker pull kkbruce/aspnetcore:<tag> 或在 Dcokerfile 裡 FROM 指定此 Image 就能取得 Server Core + dotnet-2.x-aspnetcore-runtime 的 Image。

參考:https://hub.docker.com/r/kkbruce/aspnetcore

測試之後,Got it,順利解決。


沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。