[英]BinaryFormatter used in Interop assemblies throws UnsupportedException
Microsoft 不鼓勵使用BinaryFormatter
,因為它會帶來安全問題。 請參閱: BinaryFormatter 廢棄策略。
我有一個使用Microsoft.Office.Interop.Access.Dao
互操作程序集的 .NET 6.0 WinForms 代碼。 我需要它將圖像插入 Microsoft Access 系統表MSysResources
的Data
字段中。 該字段具有Attachment
數據類型。 這是一個多值字段。 使用 DAO 是寫入該字段的唯一方法。 我的(有些縮短的)代碼是這樣的(注意:在我遷移到 .NET 6.0 之前,此代碼確實有效):
using Microsoft.Office.Interop.Access.Dao;
namespace CySoft.RibbonPro.Services;
public class AccessImageResourceLoader : IAccessImageResourceLoader
{
public void UpdateImages(string accdbFile, IEnumerable<KeyValuePair<string, Image>> images)
{
var dbe = new DBEngine(); // <====== This line throws the UnsupportedException =====
Database db = dbe.OpenDatabase(accdbFile);
Recordset rs = rs = db.OpenRecordset("SELECT * FROM MSysResources WHERE 0=1", R
ecordsetTypeEnum.dbOpenDynaset, 0, LockTypeEnum.dbOptimistic);
rs.AddNew();
rs.Fields["Type"].Value = "img";
rs.Fields["Name"].Value = name;
rs.Fields["Extension"].Value = ext;
Recordset2 rsAttachment = (Recordset2)rs.Fields["Data"].Value;
rsAttachment.AddNew();
Field2 dataField = (Field2)rsAttachment.Fields["FileData"];
dataField.LoadFromFile(imageInfo.Key);
rsAttachment.Update();
rs.Update();
rs.Close();
db.Close();
}
}
詳情僅供說明。 創建DBEngine
的第一行代碼拋出異常:
BinaryFormatter 序列化已過時,不應使用。 有關詳細信息,請參閱https://aka.ms/binaryformatter 。
調用棧是:
at System.ComponentModel.Design.DesigntimeLicenseContextSerializer.DeserializeUsingBinaryFormatter(StreamWrapper wrappedStream, String cryptoKey, RuntimeLicenseContext context)
at System.ComponentModel.Design.DesigntimeLicenseContextSerializer.Deserialize(Stream o, String cryptoKey, RuntimeLicenseContext context)
at System.ComponentModel.Design.RuntimeLicenseContext.GetSavedLicenseKey(Type type, Assembly resourceAssembly)
at System.ComponentModel.LicenseManager.LicenseInteropHelper.GetCurrentContextInfo(Type type, Boolean& isDesignTime, String& key)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Internal.Runtime.InteropServices.LicenseInteropProxy.GetCurrentContextInfo(RuntimeTypeHandle rth, Boolean& isDesignTime, IntPtr& bstrKey)
at CySoft.RibbonPro.Services.AccessImageResourceLoader.UpdateImages(String accdbFile, IEnumerable`1 images) in C:\Users\Oli\Documents\Proj\CySoft\CySoft.RibbonPro\CySoft.RibbonPro\Services\AccessImageResourceLoader.cs:line 21
AccessImageResourceLoader.cs:line 21 是var dbe = new DBEngine();
微軟希望人們使用另一種類型的序列化,例如 JSON 或 XML。 在這種情況下,這不是一個選項,因為我沒有直接使用它。 使用它的是微軟自己的 COM 庫。
問題:
如何在 .NET 6+ 中使用 Access 的Attachment
數據類型插入或更新記錄?
我的嘗試
我試圖用System.Data.OleDb
來做到這一點。 我可以用 OleDb 閱讀附件。 但任何使用 OleDb 寫入該字段的嘗試都會引發異常。
在項目文件中設置<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
標記沒有幫助。
在runtimeConfig.template.json
中設置相同的配置屬性也無濟於事。
我知道我可以通過互操作程序集使用 Access 自動化來解決問題。 但是打開Microsoft Access應用程序有一個缺點。 通過數據庫連接插入圖像要優雅得多,並且在我遷移到 .NET 6.0 之前確實有效。
您可以在這里看到有一個開關允許許可證文件的二進制序列化程序
此處的GetSavedLicenseKey
方法正在讀取
您可以通過調用以下命令在初始化DBEngine
object 之前提前設置此開關:
AppContext.SetSwitch("System.ComponentModel.TypeConverter.EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization", true);
我自己沒有嘗試過,但它應該可以工作。
此運行時開關也可以在 csproj 文件中設置,如此處所述
https://github.com/dotnet/runtime/blob/main/docs/workflow/trimming/feature-switches.md
任何定義屬性的功能開關都可以在 csproj 文件或命令行中設置為任何其他 MSBuild 屬性。 那些沒有預定義屬性名稱的值可以在 csproj 文件中使用以下 XML 標簽設置。
<RuntimeHostConfigurationOption Include="<AppContext-Setting>"
Value="false"
Trim="true" />
最后的話:在這個博客上還有更多關於升級到 .NET 6.0 的詳細信息,其中解釋了這個標志的另一種方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.