2015-03-26 2 views
0

J'ai un code hérité qui importe Excel (* .xls) à notre base de données, puis déplace le fichier dans un répertoire spécifique après le traitement.OleDbConnection verrouille le fichier Excel xls si le fichier est corrompu

Le code fonctionne correctement sauf dans un cas, lorsque le fichier est corrompu (même MS Excel ne peut pas l'ouvrir)! Qu'est-ce qui se passe dans ce cas est qu'un System.AccessViolationException jeté à l'ouverture de la connexion!

Voici comment le code ressemble à:

 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(); 
     } 

Voici les détails d'exception ...

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() 

Comme vous pouvez le voir, je suis rattrapent cette exception et le traiter, puis quand le code essaie de déplacer le fichier dans un autre répertoire, j'ai l'exception suivante:

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) 

J'ai essayé d'utiliser une autre bibliothèque, comme LinqToExcel, mais l'a trouvé en interne utilise la même implémentation que la mienne, alors c'est le même problème!

J'ai également essayé d'exécuter le garbage collector après la fermeture de la connexion (comme vous le voyez dans le code ci-dessus) mais j'ai été confronté au même problème!

Une idée?

Répondre

0

J'ai essayé de jouer la principale solution à la question sans résultat :(

J'ai même vérifié le code .NET Framework et peut voir handles de fichiers quelque part dans le code, mais n'a malheureusement pas déboguer le code :(

J'ai essayé de décompiler le code .NET Framework, mais aussi échoué :(

Enfin. i t se termine que je devrais utiliser une autre solution, et puisque selon l'existence de MS Office dans la machine de production n'est pas une option, je suis allé à ExcelDataReader, la bibliothèque open source qui lit les fichiers * .xls comme des flux binaires, et voici comment le code final ressemble à:

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... 
    } 
}  

Et cette solution fonctionne pour moi!

0

J'ai le même problème en ce moment, ma seule solution est de lire le fichier Excel en utilisant Microsoft.Office.Interop.Excel et de définir le 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); 
      } 

     } 

... fonctionne bien

+0

Il semble que Excel doit être installé dans la machine de production! En outre, cette solution est-elle adaptée à certaines versions d'Office? –