﻿# 關於【在 GDI+ 中發生泛型錯誤】出現的時機

我之前也曾經在處理圖片相關工作時遇過 "**在 GDI+ 中發生泛型錯誤**" 的錯誤，最近我們又再次遇到了，雖然這類問題多試幾次就很快能解決，但因為同樣的問題出現好幾次了，卻不太知有哪些出現的時機，因此做了一些研究，以便於下次更快速的判斷解決之道。

我先把中、英文錯誤訊息列出來：

-   System.Runtime.InteropServices.ExternalException: **在 GDI+ 中發生泛型錯誤**。
-   System.Runtime.InteropServices.ExternalException: **A generic error occurred in GDI+**

[GDI](http://en.wikipedia.org/wiki/Graphics_Device_Interface) 的全名是 [Graphics Device Interface](http://en.wikipedia.org/wiki/Graphics_Device_Interface) 的縮寫，是在 Windows 平台內十分重要的核心元件，負責處理許多跟影像物件有關的工作，包括繪製直線、曲線、字型、材質、處理縮圖、裁切圖片、...等。而 [GDI+](http://msdn.microsoft.com/en-us/library/ms533798\(VS.85\).aspx) 則是以 C++ 語言所開發的 GDI 介面，可直接利用系統硬體(顯示卡)資源對圖片相關操作進行加速處理，詳細的技術細節可參考 [Graphics Device Interface - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Graphics_Device_Interface) 的說明。

在 .NET Framework [BCL](http://en.wikipedia.org/wiki/Base_Class_Library) 中所有與繪圖有關的類別 ([System.Drawing 命名空間](http://msdn.microsoft.com/zh-tw/library/system.drawing.aspx)) 也都幾乎不是 Managed 組件，幾乎都是透過 Unmanaged GDI+ 元件進行圖形操作，所以只要發生 GDI+ 的錯誤就**一定不是** .NET 程式**語法**的錯誤，而且錯誤訊息是直接從 GDI+ 傳來的，繁體的作業系統就會回應中文訊息、英文的作業系統就會回應英文訊息，透過 Thread.CurrentThread.CurrentCulture 是沒辦法指定錯誤訊息的。

由於「**在 GDI+ 中發生泛型錯誤**」實在不容易除錯，尤其是 .NET 初學者更難以判斷問題發生的原因，往往是瞎子摸象、到處亂查、到處亂試。

首先，我們已經知道錯誤發生的地方**一定不是 .NET 程式語法的問題**，所我們就要找出其他可能發生的原因，我整理一些我曾經發生過的問題，以及有可能發生問題的地方供各位參考：

-   與『檔案系統』有關的問題

-   **目錄權限不足，無法寫入或無法讀取 ( 包括把檔案寫入 UNC 路徑 )  
    解決之道**: 設定正確可讀取或寫入的權限
-   **檔案權限不足，無法寫入或無法讀取 ( 包括把檔案寫入 UNC 路徑 )**  
    **解決之道**: 設定正確可讀取或寫入的權限
-   **目錄不存在，所以根本無法寫入檔案**  
    **解決之道**: 先建立目錄，然後再進行寫入 ( [Image.Save](http://msdn.microsoft.com/zh-tw/library/system.drawing.image.save.aspx) , [Bitmap.Save](http://msdn.microsoft.com/zh-tw/library/system.drawing.bitmap.save.aspx) )

-   與『圖檔格式』有關的問題

-   **透過** [**Image.FromStream**](http://msdn.microsoft.com/zh-tw/library/93z9ee4x.aspx) **載入圖片時，其** [**Stream**](http://msdn.microsoft.com/zh-tw/library/system.io.stream.aspx) **無法使用** [**Seek 方法**](http://msdn.microsoft.com/zh-tw/library/system.io.stream.seek.aspx)  
    **解決之道**: 將無法 Seek 的 Stream 先寫入 MemoryStream 再進行載入即可。在 MSDN 上 [Image.FromStream](http://msdn.microsoft.com/zh-tw/library/93z9ee4x.aspx) 的備註有寫：「在 [Image](http://msdn.microsoft.com/zh-tw/library/system.drawing.image.aspx) 的存留期內，資料流都必須保持開啟。」
-   **遇到了無法轉換的圖檔類型**  
    **解決之道**: 一般來說，GIF, JPEG, PNG 應該都沒問題，但還是有些圖檔格式無法透過 GDI+ 進行轉換，這時也會發生錯誤。遇到這個問題必須透過 UI 告訴使用者避開一些無法轉換的圖檔類型。我之前會遇到這個問題是因為在測試時亂選圖，剛好選到一張不能轉換成功的圖 ( 註: 該圖檔好像是顏色數非常少的 GIF 檔，年代有點久遠我記不太清楚了 )

我能想到的只有這些，總之跟 .NET 沒關係就是了，如果下次再遇到類似的問題，以上幾種狀況還找不到解法的話，請多多查詢 MSDN 並多看一下「備註」的部分，或參考以下相關連結。

**相關連結**

-   [Graphics Device Interface - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Graphics_Device_Interface)
-   [Error message when you use the Image.Save method to create a very large GIF file in Windows Server 2003 or in Windows XP: "System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+"](https://web.archive.org/web/20141212210251/http://support.microsoft.com/kb/915415)
-   [Bitmap and Image constructor dependencies](https://web.archive.org/web/20080319095039/http://support.microsoft.com/kb/814675) ( 內有 GDI+ 操作圖片時的重要觀念 )
-   [.NET 2.0 縮圖後上傳圖檔到 SERVER時，出現 "在 GDI+ 中發生泛型錯誤" ...](http://social.msdn.microsoft.com/Forums/zh-TW/236/thread/9a8838f6-a24c-4d75-b792-db08afa11c3f)
-   [Understanding “A generic error occurred in GDI+.” Error](http://www.kerrywong.com/2007/11/15/understanding-a-generic-error-occurred-in-gdi-error/)
