2017-02-19 50 views
2

我已經嘗試了許多解決方案,但沒有工作請幫我解決這個問題。 下面是即使釋放資源後SSIS腳本任務即使在釋放資源後也無法關閉Excel

using Excel = Microsoft.Office.Interop.Excel;   
      Excel.Application xlApp = null; 
      Excel.Workbooks workbooks = null; 
      Excel.Workbook xlWorkbook = null; 
      Excel.Worksheet worksheet = null; 
      Excel.Range xlRange = null;       
     try 
      { 

      xlApp = new Excel.Application(); 
      xlApp.DisplayAlerts = false; 
      xlApp.AskToUpdateLinks = false; 
      workbooks = xlApp.Workbooks; 
      xlWorkbook = workbooks.Open("sample.csv", 2, true); 
      xlWorksheet = xlWorkbook.Sheets[1]; 
      xlRange = xlWorksheet.UsedRange; 
      int rowCount = xlRange.Rows.Count; 
      for (int row = 2; row <= rowCount; row++) 
      { 
       //some logic 

      } 
      } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
    finally //releasing all resources 
    { 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     Marshal.ReleaseComObject(xlRange); 
     Marshal.ReleaseComObject(xlWorksheet); 
     xlRange = null; 
     xlWorksheet = null; 
     xlWorkbook.Close(); 
     Marshal.ReleaseComObject(xlWorkbook); 
     xlWorkbook = null; 
     workbooks = null; 
     xlApp.Quit(); 
     Marshal.ReleaseComObject(xlApp); 
     xlApp=null; 
} 

使用的代碼,仍然可以看到一個Excel進程

回答

0

看起來你是在正確的軌道上。但是,您目前的ExcelApplication是您將在任務監視器中看到的實際過程以及在WordApplication被終止之前需要關閉的ExcelDocument。

在這個簡單的例子看看:

public void Foo(string filePath) 
{ 
    var application = new Excel.Application(); 

    // do your stuff here... 
    var document = application.Workbooks.Open(filePath, ReadOnly: true, Visible: false); 

    // this is the magic: clear 'application' and 'document', 
    // once the work is finished 
    if (document != null) 
     document.Close(SaveChanges: false); 

    if (application != null) 
     application.Quit(SaveChanges: false); 

    document = null; 
    application = null; 
} 

在這裏你可以看到,我們實際上是正確關閉()工作簿(文檔)和退出()應用。這是你在最後一節中所做的一些事情,但請記住,在之前,你可以將變量初始化爲,然後才能進入try ...部分。

我的建議是:不要手動調用任何垃圾回收(GC)和元帥的東西。如果你不確定它的作用,它會在稍後產生副作用而傷害到你。接下來,您可以通過圍繞ExcelApplication和ExcelWorkbook添加一個漂亮的using (...)結構來進一步改進示例。

1

有兩種方法來實現這一目標:

第一種方法

您可以創建自定義ReleaseObject功能如下圖所示:

private void ReleaseObject(object obj) 
{ 
    try { 
     int intRel = 0; 
     do { 
      intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); 
     } while (intRel > 0); 

    } catch (Exception ex) { 

     obj = null; 
    } finally { 
     GC.Collect(); 
    } 
} 

,並使用下面的代碼順序:

xlWorkBook.SaveAs("...."); 
xlWorkBook.Close(); 
xlApp.Quit(); 

ReleaseObject(xlRange); 
ReleaseObject(xlWorkSheet); 
ReleaseObject(xlWorkBook); 
ReleaseObject(xlApp); 

第二種方法

創建腳本任務內部類,創建一個函數,得到Excel.Application的進程ID,並殺死它

using Excel = Microsoft.Office.Interop.Excel; 
using System.Runtime.InteropServices; 
using System.Diagnostics; 

class Sample 
{ 
    [DllImport("user32.dll")] 
    static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); 

    Process GetExcelProcess(Excel.Application excelApp) 
    { 
     int id; 
     GetWindowThreadProcessId(excelApp.Hwnd, out id); 
     return Process.GetProcessById(id); 
    } 
} 

,然後你可以使用GetExcelProcess(XlApp).Kill();

0

正確清洗up Interop.Excel對象很難。做錯了,你可能會陷入一個擁有大量殭屍Excel實例的SQL或SSIS機器。

enter image description here

互聯網是litteredwithadvice如何正確Close()Quit()ReleaseObject()Interop.Excel對象。適用於您的建議將取決於您調用對象的順序以及您調用的方法。例如,如果您使用了double dot method,那麼您創建了一個不可關閉的對象。即使你聽取了所有的建議並且構建你的代碼以避免陷阱,但是當SSIS包被部署到服務器時,情況會發生變化。微軟已經基本告訴開發者not do this

微軟目前並不提倡,不支持,Microsoft Office應用程序自動化從任何無人蔘與的非交互式客戶端應用程序或組件(包括ASP,ASP.NET,DCOM和NT Service),因爲Office Office在此環境中運行時可能會出現不穩定的行爲和/或死鎖。

奇怪的事情發生。而且,它不會縮放。包將共享相同的Excel實例。一個程序包的清理程序可以殺死另一個程序包的正在運行的操作。

聽着,我知道有很多如何在Interop.Excel上以及如何清理它們的方法。但是,這些文章針對的是在自己的機器上運行單個代碼實例的個人。不建議使用SSIS的企業環境。是的,這太臭了。

但是,有解決方案! NetOfficeInterop.Excel類似,有助於處理COM對象的關閉和處理。我的強烈偏好是EPPlus API它非常輕便,類似於Interop.Excel,速度提高10倍,沒有清理困難。除了打印和宏之外,Interop可以完成幾乎所有的操作。即使比C#更好,也會開始使用微軟提供的built-in SSIS Excel components來執行ETL工作。

祝你好運!