2015-03-26 3 views
0

У меня есть устаревший код, который импортирует Excel (* .xls) в наш db, а затем переместите файл в конкретный каталог после обработки.OleDbConnection блокирует файл 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, но обнаружила, что она внутренне использует ту же реализацию, что и моя, тогда она имеет ту же проблему!

Я попытался также запустить сборщик мусора после закрытия соединения (как вы видите в приведенном выше коде), но столкнулся с той же проблемой!

Любая идея?

ответ

0

Я пытался играть вокруг главного решения в вопросе без каких-либо результатов :(

Я даже проверил .NET Framework код и может увидеть файл обрабатывает где-то в коде, но, к сожалению, не удалось отладить код :(

Я попытался декомпилировать .NET Framework код, но не слишком :(

Наконец, я t заканчивается тем, что я должен использовать другое решение, и поскольку в зависимости от наличия 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... 
    } 
}  

И это решение работает для меня!

0

У меня такая же проблема прямо сейчас, мое единственное решение - прочитать файл excel с помощью Microsoft.Office.Interop.Excel и установить MsoFileValidationMode = msoFileValidationSkip;

Excel.Application xlApp = new 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); 
      } 

     } 

... хорошо работает

+0

Кажется, что Excel должен быть установлен на производственной машине! Кроме того, имеет ли это решение проблемы с определенными версиями Office? –