繁体   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