2024/2/24

Could not load file or assembly 'System.Buffers' 無法載入檔案或組件....

最近遇到C# windows form 的老專案必須使用 smtpclient寄信,但因為MailServer限制使用starttls與587port寄信,使用原來net 的 smtpclient 不能支援此方法,所以必須改用Mailkit組件。

由於原來專案使用.net  Framework 4.5.x版本過舊,咬牙升級為 .net Framework 4.7.1。 Mailkit看似搞定,但在建置過程中卻會看到警訊,

 Could not load file or assembly 'System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

此問題的發生原因是Mailkit需要較新版本的System.Buffers等組件dll,透過nuget更新版本後,專案仍然記載要去拿原來的dll。

解決方法如下

<1>重新註冊元件

透過系統VisualStudio選單底下的開發人員終端機介面(要使用系統管理員權限執行),進到專案packages目錄之下擺放特定組件的位置,重新註冊元件。
教學文內的目錄是 netstandard2.0,傳統.net framework要選.net framework的版本
cd d:/project_folder/packages/System.Buffers.4.5.1/lib/netstandard2.0/
然後執行
gacutil /i System.Buffers.dll
接著回到Visual Studio內的Nuget 套件管理員( package manager console),透過powershell重新安裝套件。
update-package -reinstall
用文字模式打開 csproj 檔案,確認引用組件的版本改為4.0.3.0
(Version=4.0.2.0 to Version=4.0.3.0 )。


<2>進行重新導向組件版本(Binding Redirect)

手動編輯應用程式組態檔(App.Config)。
<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

上述的答案做完之後,因為系統有使用App.Config的關係,在建置完專案後,請記得將有記載對應組件關係的.Config檔案部屬到Production正式環境。筆者為了怕覆蓋正式環境上的組態,自己略過這個檔案,導致一直反覆出現組件不相容錯誤,結果其實是自己犯了低級錯誤而不自知!!!!!

解法的原文在此。
https://stackoverflow.com/questions/63019110/could-not-load-file-or-assembly-system-buffers-version-4-0-2-0


2023/7/31

Windows 上IIS 匯入SSL憑證時,出現"指定的網路密碼錯誤"訊息(.pfx)

公司使用的伺服器SSL都是向TWCA購買。以往自TWCA下載的憑證,包含server.cer與 server.key,經過 OpenSSL 轉換成.pfx後,就可以匯入到IIS使用。 

從 https://slproweb.com/products/Win32OpenSSL.html下載執行檔安裝後,選擇裝在C:\Program Files\OpenSSL-Win64\bin 下,再以指令執行轉換。

在程式目錄下輸入 openssl version,則可以查看 openssl的版本。

但如果憑證要裝在Server 2016/2019以上版本的Windows Server,會認為openssl的預設轉換加密演算法不夠安全,導致在匯入pfx時產生"指定的網路密碼錯誤"訊息。看起來是製作pfx時輸入密碼的問題,但其實一點關係也沒有......也有文章說要將openssl 改裝回舊版本,但這是不對的。

此時,請依照以下方式轉換憑證檔案(指令內的資料夾名稱請自行修改為實際內容)。 


--2023版本
openssl pkcs12 -macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES  -export -out d:\ssl_2023\aloha2023.pfx -inkey d:\ssl_2023\server.key -in d:\ssl_2023\server.cer -certfile d:\ssl_2023\uca.cer

--以前能夠正常執行的版本
openssl pkcs12 -export -out d:\ssl_2022\QQQserver2022.pfx -inkey d:\ssl_2022\server.key -in d:\ssl_2022\server.cer -certfile d:\ssl_2022\uca.cer

2023/4/6

C# 非同步程式抓取資料的開發技巧(async, wait, web crawler)

最近有個side project的需求,是需要利用爬蟲去抓取國內外官方機構的Meta data後設資料,對現有的資料做補充。但這些抓取資料的來源格式差異很大,而且刻出來的程式是希望可以打包給不太懂電腦的使用者,執行幾千筆資料的抓取與更新,因此使用python+爬蟲的solution就不太適用。最後,決定用 c# 寫windows form。

但由於抓資料的來源不是後端資料庫而是前端網站,爬資料的時候可能會遇到連線中斷、網路速度遲緩等各種情形,若是幾千筆跑下來,在程式執行完畢前不僅程式會有凍結的情形發生,使用者也會抱怨非常緩慢。所以在開發上選擇使用非同步的寫法。

設計上針對XML、HTML、JSON三種資料來源轉寫三個解析器,以下有幾個設計過程中的心得:

  • 使用 HttpClient而非古早時代的WebRequest寫法抓取資料(相容.NET Core)。
  • 為查詢請求加上瀏覽器header(實際測試,空的請求會被視為機器人而遭拒絕)。
  • 解析的設定(如 xml的節點、Xpath等)另外寫在設定檔中,提高修改程式的彈性。
  • 為每段請求加上一定的delay,以免被視為濫用或過度存取。
  • 為了解析網站資料,用到HtmlAgilityPack套件。另外也需要regexp來解析標籤資料。

實作程式時要加上存取修飾詞 async ,回傳值必須用Task<T>包起來(T是指你的程式想要的型別)。

public async Task<SearchResultData> getDataFromJson(string Oid, string keyword, SearchSetting policy, bool interactive)

{

    //....你的查詢邏輯

    return SearchResultData;

}

呼叫時,在程式之前加上 await ,告訴程式必須等待回傳值。

List<SearchResultData> metaList = new List<SearchResultData>();

 if (policy.Media == "html")

{

    metaList.Add(await getDataFromHtml("virtual", keyword, policy, interactive));

 }

 如果這段程式又被其他程式Caller呼叫,則呼叫的Caller程式建議也要加上async 存取修飾詞。這樣C#才會在背後實作依照發出請求的先後順序回傳資料。否則各個請求資料回傳的順序會是真的完全非同步,也就是同一筆資料先後發出去三個Query1,Query2,Query3,回傳的順序卻會顯示2,3,1。學理上是完全可以理解的,但在實務運作上這樣卻不利於我們整理蒐集回來的資料。

2022/11/11

發瘋的Arduino Uno開發版Reset方法

 

最近迷上了用Arduino玩些小程式,但是對於Windows 裝置管理員常常會偵測不到開發板,感到十分困擾。甚麼線沒插好、驅動程式沒裝的步驟,全試過了,但就是找不到板子跟COM3。


想跟原來店家抗議,又怕被當成奧客,只好一直反覆實驗,換不同的Windows筆電、桌電來試,但仍然無效。結果今天仔細看了Reset方法,居然是連按Reset鍵兩下!(Click the button two times in succession.)。然後到裝置管理員內的檢視選擇顯示隱藏裝置,果然有奇蹟出現.....






https://support.arduino.cc/hc/en-us/articles/5779192727068-Reset-your-board