最近使用UnRARNet 處理 RAR格式的壓縮檔。UnRARNet 是由 RARLab 隨 unrar.dll 控制項一起提供的.net 平台的封裝。UnRARNet 使用VB.net語言,應該說對unrar.dll 進行了近乎完美的封裝,幾乎所有壓縮和解壓縮工作都完成的很漂亮。
不過,最近在測試解壓縮檔案時,遇到一個 System.Runtime.InteropServices.SEHException 異常,異常資訊是“外部組件發生異常”。具體位置是在 Decompressor 類的 LoadFileList() 方法中,其中有一句
mRARHandle = RAROpenArchiveEx(uRAREx)
是調用 unrar.dll 外部組件的RAROpenArchiveEx() 方法,異常就發生在這裡。
微軟關於SEHExcption的描述中說:
SEHException 類處理從Unmanaged 程式碼引發的、但尚未映射到另一個 .NET Framework 異常的 SEH 錯誤。
SEHException 類還響應
HRESULT E_FAIL(它具有值
0x80004005)。
.NET Framework 經常會遇到非託管 SEH 異常,這些異常自動對應到託管等效項。例如,STATUS_NO_MEMORY SEH 異常自動對應到 OutOfMemoryException 類,而 STATUS_ACCESS_VIOLATION SEH 異常自動對應到 NullReferenceException 類。但是預設情況下,任何未自動對應到特定異常的 SEH 異常將映射到 SEHException 類。
我用Google搜尋網頁和Google Groups,都沒有發現解決這類問題的方法,看來我足夠幸運:),讓我先碰到了。
經過仔細分析,發現問題出在壓縮檔的注釋上,當注釋長度超過一個臨界值時,就會發生 SEHException 外部組件異常。RAR 命令指南中提到RAR 壓縮包的最大注釋長度是 62000 位元組,而測試的壓縮檔注釋只有19000多個位元組,完全沒有超出最大注釋長度。因為注釋長度而發生異常似乎沒有道理。難道是UnRARNet有問題?
再回過頭看 Decompressor 類,發現在 Init() 方法中有這麼一段代碼:
uRAREx.CmtBuf = Space(16384)
uRAREx.CmtBufSize = 16384
uRAREx.ArcName = mRARFile
uHeaderEx.CmtBuf = Space(16384)
原來,UnRARNet 將預設的注釋長度設定成了 16384,難怪解壓縮時發生異常了。將注釋長度設定成RAR 壓縮包的最大注釋長度62000,測試通過:)