2011-03-01 64 views
0

我有一個從Excel文件導入數據的應用程序。它創建一個excel COM對象並從中讀取數據。之後,我釋放所有對象並釋放所有的Excel對象。 它使用安裝在本機上的excel在Windows服務器上執行所有操作。導入文件存儲在用戶的機器上。只是另一個Excel COM問題

如果我嘗試從用戶機器上的Excel中打開的文件導入數據,則應用程序無法釋放Excel COM對象。

任何ideea我該如何解決這個問題(無論如何關閉該實例)?

謝謝!

我已經添加了我的代碼:

public DataTable DoImportToDataTable(BackgroundWorker worker, string strPath, int columnCount, bool bIgnoreFirstLine = true) 
    { 
     bool importOk = false; 
     DataTable datatable = new System.Data.DataTable("ExcelContent"); 

     Excel.Application excelApp = null; // the excel application instance 
     Excel.Workbook importFile = null; // the export workbook 
     Excel.Worksheet sheet = null; // the worksheet 
     Excel.Range range = null; 
     Excel.Sheets sheets = null; 
     try 
     { 
      excelApp = new Excel.Application(); 
      excelApp.DisplayAlerts = false; 
      // try to open the file 
      importFile = excelApp.Workbooks.Open(strPath, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); 

      sheets = importFile.Worksheets; 
      sheet = (Excel.Worksheet)sheets.get_Item(1); 

      range = sheet.UsedRange; 


      int usedColumnsCount = range.Cells.Columns.Count; 
      int usedRowsCount = range.Cells.Rows.Count; 

      if (usedColumnsCount < columnCount) 
      { 
       throw new ImportException("Wrong file structure! Please check and correct the import file to match the requirements."); 
      } 

      Object[,] values = (Object[,])range.Value2; 

      data.Clear(); 

      int row = 1; 
      // read data from used range 
      while (row <= usedRowsCount) 
      { 
       if (row == 1 && bIgnoreFirstLine) 
       { 
        row++; 
        continue; 
       } 

       if (worker.CancellationPending) 
       { 
        throw new Exception("Operation cancelled"); 
       } 

       ArrayList line = new ArrayList(); 
       bool bIsLineEmpty = true; 
       for (int i = 0; i < columnCount; i++) 
       { 
        if (values[row, i + 1] == null) 
         line.Add(""); 
        else 
        { 
         line.Add((String)values[row, i + 1].ToString()); 
         bIsLineEmpty = false; 
        } 
       } 

       if (bIsLineEmpty) 
        // return after first empty line in range 
        break; 


       datatable.Rows.Add(line.ToArray()); 
       data.Add(line); 
       row++; 
      } 
      // cleanup 
      excelApp.DisplayAlerts = false; 

      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 

      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 

      if (range != null) { 
       Marshal.FinalReleaseComObject(range); 
       range = null; 
      } 

      if (sheet != null) { 
       Marshal.FinalReleaseComObject(sheet); 
       sheet = null; 
      } 
      if (sheets != null) 
      { 
       Marshal.FinalReleaseComObject(sheets); 
       sheets = null; 
      } 
      if (importFile != null) 
      { 
       importFile.Close(Type.Missing, Type.Missing, Type.Missing); 
       Marshal.FinalReleaseComObject(importFile); 
       importFile = null; 
      } 
      if (excelApp != null) 
      { 
       excelApp.Quit(); 
       Marshal.FinalReleaseComObject(excelApp); 
       excelApp = null; 
      } 


      importOk = true; 
     } 
     catch (COMException e) 
     { 
      message = e.Message; 
     } 
     catch (ImportException e) 
     { 
      message = e.ImportMessage; 
     } 
     catch (Exception e) 
     { 
      message = e.Message; 
     } 
     finally 
     { 
      if (!importOk) 
      { 
       GC.Collect(); 
       GC.WaitForPendingFinalizers(); 

       GC.Collect(); 
       GC.WaitForPendingFinalizers(); 

       if (range != null) 
       { 
        Marshal.FinalReleaseComObject(range); 
        range = null; 
       } 

       if (sheet != null) 
       { 
        Marshal.FinalReleaseComObject(sheet); 
        sheet = null; 
       } 
       if (sheets != null) 
       { 
        Marshal.FinalReleaseComObject(sheets); 
        sheets = null; 
       } 
       if (importFile != null) 
       { 
        importFile.Close(Type.Missing, Type.Missing, Type.Missing); 
        Marshal.FinalReleaseComObject(importFile); 
        importFile = null; 
       } 
       if (excelApp != null) 
       { 
        excelApp.Quit(); 
        Marshal.FinalReleaseComObject(excelApp); 
        excelApp = null; 
       } 
      } 
     } 
     return datatable; 
    } 

回答

0

我剛剛試過你所描述的,是這樣的:

 _Application app = new Application(); 
     Workbook wb = app.Workbooks.Open(@"C:\Users\josip.INCENDO\Desktop\Payment (uplate) - primjer.xls"); 
     wb.Close(); 
     wb = null; 
     app.Quit(); 
     app = null; 

而且這工作完全正常,即使用戶已經打開的文檔。你可以發佈代碼嗎?

+0

感謝您的迴應!我已經添加了代碼。 – maephisto 2011-03-01 09:34:13

+0

我試過你的代碼,剛剛註釋掉了你正在做的與文件相關的東西,並且它工作正常。 我用Excel打開文件=>在任務管理器中有1個Excel進程。 我啓動程序,它會打開文件。 =>在任務管理器中有2個Excel進程。該程序結束,關閉應用程序。 =>在任務管理器中有1個Excel進程。 我關閉了Excel應用程序=>在任務管理器中沒有Excel進程。 – nogola 2011-03-01 09:51:35

+0

感謝您的快速反應。我在本地獲得相同的行爲。問題是當應用程序運行在Windows服務器上,並且該文件被存儲並在另一臺機器上打開時 – maephisto 2011-03-01 10:09:26

0

看一看這裏:Excel 2007 Hangs When Closing via .NET

始終分配您的Excel對象局部變量,永遠不會「兩個點下來」,像這樣:

//fail 
Workbook wkBook = xlApp.Workbooks.Open(@"C:\mybook.xls"); 

//win 
Worksheets sheets = xlApp.Worksheets; 
Worksheet sheet = sheets.Open(@"C:\mybook.xls"); 
... 
Marshal.ReleaseComObject(sheets); 
Marshal.ReleaseComObject(sheet); 

.NET的COM對象創建一個包裝這是你看不見的東西,直到GC編織它的魔法纔會被釋放。

+0

謝謝!我知道這個問題,並將它們應用於我的代碼。如果該文件未在本地打開,則該實例將關閉而不會出現問題。但是,如果文件已打開,則此實例無法關閉 – maephisto 2011-03-02 12:06:55