SQL Server CLR 的執行失敗,TypeInitializationException

本文可協助您解決執行 SQL Server CLR 物件失敗並傳回 TypeInitializationException 例外狀況的問題。

適用于:  SQL Server
原始 KB 編號:   4576575

徵狀

重要

本文包含的資訊可告訴您如何協助降低安全性設定,或如何關閉電腦上的安全性功能。 您可以進行這些變更,以解決特定的問題。 在您進行這些變更之前,建議您先評估在您的特定環境中實施此解決方法的相關風險。 如果您要執行此解決方法,請採取任何適當的額外步驟,協助保護電腦。

在您安裝適當的 .NET Framework 更新以修正CVE-2020-1147中所述的漏洞後,執行使用通用語言執行時間建立資料庫物件 (CLR) 整合將 XML 讀入DataSet 及 DataTable 安全性指南物件會失敗。 這是因為 TypeInitializationException 例外狀況中有嵌套的 FileNotFoundException 例外狀況。 此問題表示無法載入 System.Drawing 元件。

如需參考,請參閱下列範例:

Msg 6522,Level 16,State 1,Procedure [CLR object],第0行 [批次起始行 0] 執行使用者定義的常式或匯總 "CLR 物件" 時,發生 .NET Framework 錯誤:
TypeInitializationException: ' Scope ' 的類型初始值設定項引發例外狀況。 ---> FileNotFoundException:無法載入檔案或元件 ' System.Drawing、Version = 4.0.0.0、Culture = 中立性、PublicKeyToken = <Token> ' 或其其中一個相依性。 系統找不到指定的檔案。
TypeInitializationException:
在 TypeLimiter 中,IsTypeUnconditionallyAllowed (Type type)
在 TypeLimiter 中,IsAllowedType (Type type)
在 TypeLimiter 中,EnsureTypeIsAllowed (Type type,TypeLimiter capturedLimiter) DataColumn at UpdateColumnType (Type type,StorageType typeCode)
在 DataColumn。ctor (字串 columnName、輸入 dataType、字串運算式、MappingType 類型)
在 XSDSchema (XmlSchemaElement elem,DataTable table,Boolean isBase)
XSDSchema (XmlSchemaParticle pt DataTable table,ArrayList tableChildren,Boolean isBase)
在 XSDSchema。 HandleComplexType (XmlSchemaComplexType ct,DataTable table,ArrayList tableChildren,Boolean isNillable)
(XSDSchema XmlSchemaElement node,XmlSchemaComplexType typeNode,Boolean isRef)
在 XSDSchema (XmlSchemaElement 節點)
XSDSchema (XmlSchemaParticle pt DataTable table,ArrayList tableChildren,Boolean isBase)
在 XSDSchema。 HandleComplexType (XmlSchemaComplexType ct,DataTable table,ArrayList tableChildren,Boolean isNillable)
(XSDSchema XmlSchemaElement node,XmlSchemaComplexType typeNode,Boolean isRef)
在 XSDSchema (XmlSchemaElement 節點)
在 XSDSchema (XmlSchemaSet schemaSet,DataSet ds)
DataSet 在 InferSchema 中 (Xml xdoc,String [] excludedNamespaces,XmlReadMode mode)
在 [data ...]

解決方案

此問題已在2020年10月13日 Security-Only 更新中重新發佈 2020 .NET Framework。

如需詳細資訊,包括如何取得此修補程式,請參閱.NET Framework 于2020年7月的安全性更新

因應措施

警告

這個因應措施可能會使電腦或網路更容易遭受惡意使用者或惡意軟體 (例如病毒) 的攻擊。 我們不建議此方法,而是提供此資訊,因此您可以自行決定是否要執行此方法。 採用此因應措施需自行承擔風險。

若要將不受信任之 XML 資料的應用程式,反序列化為 DataSet 或物件的實例 DataTable ,建議您使用另一種方法來存取資料。 若應用程式唯讀取信任的 XML 資料,您可以嘗試下列其中一種解決方法。

注意

建議的方法1和2是可在本機進行的變更。 方法3是整個系統。

警告

這些解決方法會移除類型限制,將 XML 反序列化為 DataSet 和物件的實例 DataTable 。 這可能會在應用程式讀取不受信任的輸入時,開啟安全性漏洞。

  • 解決方法1:撥打 AppCoNtext。 SetSwitch

    變更 SQL CLR 物件代碼的開頭,將 AllowArbitraryDataSetTypeInstantiation 參數設定為 true。 您必須針對每個適用的 SQL CLR 物件執行這項操作。 請參閱下列的範例。

    螢幕擷取畫面顯示 SQL CLR 物件代碼變更的範例。

    如需詳細資訊,請參閱 DataSet 和 DataTable 安全指導方針。

  • 解決方法2:建立或變更每個適用實例的 Sqlservr.exe.config 檔案

    此方法僅適用于實例本身。

    重要

    我們無法保證 SQL Server 更新或實例升級時,不會覆寫此變更。 我們建議您判斷變更在實例更新或升級後是否會繼續存在。

    1. SQL Server 的預設及命名實例的檔案位置中,找出 Sqlservr.exe.config 檔案:

      %ProgramFiles%\Microsoft SQL Server\<Instance_ID>.<Instance Name>\MSSQL\Binn\

    2. <runtime> 節點內,但在任何嵌套節點之外,新增下列行:

      <AppContextSwitchOverrides value="Switch.System.Data. AllowArbitraryDataSetTypeInstantiation=true"/>
      
    3. 儲存檔,然後重新開機實例。

      請參閱下列 SQL Server 2016 實例的範例。

      螢幕擷取畫面顯示 SQL Server 2016 實例的範例。

  • 解決方法3:建立 System.Drawing 元件

    全域組件快取 (GAC) 中的 DLL 檔案,手動建立 SQL Server 中的 System.Drawing 元件,然後重新建立使用 DataSet ReadXML 或 ReadXML 的元件。 例如:

    CREATE ASSEMBLY [Drawing] FROM 'C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll' WITH PERMISSION_SET = UNSAFE GO
    
  • 解決方法4:建立登錄子機碼

    重要

    請仔細遵循此解決方法中的步驟。 如果您不當地修改登錄,可能會發生嚴重的問題。 在您進行修改之前,請先備份登錄,做為還原之用,以免發生問題。

    此解決方法會影響伺服器上的所有 .NET 應用程式。 因此,如果您無法使用其他的方法,則應該使用此方法做為最後的手段。

    1. 開啟 [登錄編輯程式]。

    2. 找到下列子機碼:

      KEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AppContext

    3. 建立 REG_SZ 值,如下所示。

      名稱 AllowArbitraryDataSetTypeInstantiation。
    4. 重新開機所有 SQL Server 實例。

      請參閱下列的範例。

      登錄編輯程式中 AppCoNtext 登錄機碼的螢幕擷取畫面。

其他相關資訊

這項問題是由於最近 .NET Framework 安全性更新的動作,修正 .NET Framework XML 內容標記驗證。 SQL Server 未讀取 XML 至任何或物件實例的 CLR 物件 DataSet DataTable 將不會受到影響。