簡體   English   中英

OleDbConnection鎖定Excel xls文件,如果該文件已損壞

[英]OleDbConnection locks Excel xls file if the file is corrupted

我有一個遺留代碼,可以將Excel(* .xls)導入我們的數據庫,然后在處理后將文件移至特定目錄。

該代碼可以正常工作,除非在一種情況下該文件已損壞(即使MS Excel也無法打開它)! 在這種情況下,發生的情況是在打開連接時拋出了System.AccessViolationException

代碼如下所示:

        string connectionString = string.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""", filePath);
        OleDbConnection connection = new OleDbConnection(connectionString);
        try
        {
            connection.ConnectionString = connectionString;
            connection.Open(); //<<<--- exception throws here
            //file processing
        }
        catch (Exception e)
        {
            //exception handling
        }
        finally
        {
            connection.Close();
            connection.Dispose();
            connection = null;
            GC.Collect();
        }

這是例外詳細信息...

System.AccessViolationException was caught
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=System.Data
  StackTrace:
       at System.Data.Common.UnsafeNativeMethods.IDBInitializeInitialize.Invoke(IntPtr pThis)
       at System.Data.OleDb.DataSourceWrapper.InitializeAndCreateSession(OleDbConnectionString constr, SessionWrapper& sessionWrapper)
       at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)
       at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
       at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup)
       at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
       at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
       at System.Data.OleDb.OleDbConnection.Open()

如您所見,我正在捕獲此異常並對其進行處理,然后當代碼嘗試將文件移動到另一個目錄時,出現了以下異常:

System.IO.IOException occurred
  Message=The process cannot access the file because it is being used by another process.
  Source=mscorlib
  StackTrace:
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.__Error.WinIOError()
       at System.IO.File.Move(String sourceFileName, String destFileName)

我試圖使用另一個庫,例如LinqToExcel ,但是發現它內部使用了與我的庫相同的實現,所以它有同樣的問題!

關閉連接后,我也嘗試運行垃圾收集器(如您在上面的代碼中看到的),但是遇到了同樣的問題!

任何想法?

我現在有同樣的問題,我唯一的解決方案是使用Microsoft.Office.Interop.Excel讀取excel文件並設置MsoFileValidationMode = msoFileValidationSkip;

Excel.Application xlApp =新的Excel.Application(); Excel.Workbook xlWorkbook;

        System.Globalization.CultureInfo CurrentCI = System.Threading.Thread.CurrentThread.CurrentCulture;
        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");

        **xlApp.FileValidation = MsoFileValidationMode.msoFileValidationSkip;** 

        xlWorkbook = xlApp.Workbooks.Open(@"C:\my file.xls");
        Excel.Sheets xlWorksheet = xlWorkbook.Worksheets;

        Excel.Worksheet worksheet = (Excel.Worksheet)xlWorksheet.get_Item(3);
        for (int i = 1; i <= 10; i++)
        {

            Excel.Range range = worksheet.get_Range("A" + i.ToString(), "B" + i.ToString()); ; //UsedRange;
            System.Array myvalues = (System.Array)range.Cells.Value2;


            string[] strArray = ConvertToStringArray(myvalues);

            foreach (string item in strArray)
            {   
                MessageBox.Show(item);
            }

        }

... 效果很好

我試圖解決這個問題的主要解決方案,但沒有結果:(

我什至檢查了.NET Framework代碼,並且可以在代碼中的某處看到文件句柄,但不幸的是未能調試代碼:(

我試圖反編譯.NET Framework代碼,但也失敗了:(

最后。 最后我應該使用另一種解決方案,並且由於不能選擇在生產計算機中使用MS Office,因此我轉到了ExcelDataReader ,它是將* .xls文件作為二進制流讀取的開源庫,下面是最終代碼如下:

using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
    using (IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream, true))
    {
        excelReader.IsFirstRowAsColumnNames = true;
        var excelFileDataSet = excelReader.AsDataSet();
        var sheetDataTable = excelFileDataSet.Tables["sheetName"];
        //other file processing code...
    }
}    

這個解決方案對我有用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM