2017-02-19 6 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; 
} 

でもリソースを解放した後、まだ1つの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; 
} 

あなたは私たち実際に適切に閉じる()ワークブック(文書)とが終了していることがわかります()アプリケーションを。これはfinallyセクションで何をやっているのかと少し異なりますが、変数はより前にに初期化されていますので、try ...セクションに入れることができます。

ここで私のアドバイスは:ガベージコレクション(GC)とマーシャルを手動で呼び出さないでください。あなたが本当に何をしているのか分からなければ、後で副作用であなたを傷つけるでしょう。次に、ExcelApplicationとExcelWorkbookの両方に素晴らしいusing (...)構造を追加することで、サンプルをさらに改善できます。

1

これを達成するための2つの方法があります。

まず方法

あなたは以下のようにカスタム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); 

第2の方法

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

を使用することができますInterop.Excelオブジェクトは難しいです。それは間違っていると、あなたはExcelのゾンビインスタンスのトンを持つSQLまたはSSISマシンを駄目にする可能性があります。

enter image description here

インターネットはどのように適切にClose()litteredwithadviceQuit()ReleaseObject()Interop.Excelオブジェクトです。あなたのために働くアドバイスは、オブジェクトをどのような順序で呼び出し、どのメソッドを呼び出すかによって異なります。たとえば、double dot methodを使用した場合、クローズ不可能なオブジェクトが作成されました。 SSISパッケージがサーバーに展開されるときに、すべてのアドバイスに注意して問題を回避するようにコードを構成しても、状況は変わります。マイクロソフトでは基本的に開発者にnot do thisと語っている。

オフィスため、Microsoftは、現在はお勧めしませんし、サポートしていない、(ASP、ASP.NET、DCOM、およびNTサービスを含む)任意の無人、非対話型クライアントアプリケーションまたはコンポーネントからのMicrosoft Officeアプリケーションの自動化この環境でOfficeを実行すると、不安定な動作やデッドロックが発生することがあります。

奇妙なことが起こります。また、縮尺も変化しません。パッケージはExcelの同じインスタンスを共有します。あるパッケージのクリーンアップルーチンは、別のパッケージの飛行中の操作を強制終了できます。

私が知っているのは、Interop.Excelの方法がたくさんありますし、それらをきれいにする方法もあります。しかし、これらの記事は、自分のマシン上でコードの1つのインスタンスを実行している個人を対象としています。 SSISを使用するエンタープライズ環境では推奨されません。はい、これは悪臭を放つ。

しかし、解決策があります。 NetOfficeInterop.Excelに似ており、COMオブジェクトのクローズと破棄の処理に役立ちます。私の強い好みはEPPlus APIです。これは非常に軽量です。Interop.Excelに似ていますが、クリーンアップの苦労なしに10倍高速です。 Interopは印刷やマクロを除いてほとんどすべてのことを行うことができます。 C#よりも優れているのは、built-in SSIS Excel componentsを使用して開始することです。これは、MicrosoftがETLの作業を行うために提供したものです。

幸運を祈る!

関連する問題