2016-09-01 10 views
0

私はwinformアプリケーションでExcelプロセスを終了しようとしています。私は、SOや他のサイト上の記事の多くを経ており、これは私が今やっているものです:最初のインスタンスを除くすべてのExcelプロセスを閉じることができます

private void lsvSelectedQ_SelectedIndexChanged(object sender, EventArgs e) 
     { 
      FillSelectedItems(); 
     } 

private void FillSelectedItems() 
     { 
      string filepath = string.Empty; 
      string reportname = lblreportname.Text; 
      filepath = Application.StartupPath + "\\StandardReports\\" + reportname + ".xls"; 

      Microsoft.Office.Interop.Excel.Application xlApp; 
      Microsoft.Office.Interop.Excel.Workbook xlWorkBook; 
      Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet; 
      object misValue = System.Reflection.Missing.Value; 

      xlApp = new Microsoft.Office.Interop.Excel.Application(); 
      xlWorkBook = xlApp.Workbooks.Open(filepath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0); 
      List<string> WorksheetList = new List<string>();   

      xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets.get_Item("Config"); 

      Microsoft.Office.Interop.Excel.Range objRange = null; 

      objRange = (Microsoft.Office.Interop.Excel.Range)xlWorkSheet.Cells[6, 2]; 
      if (objRange.Value != null) 
      { 
       int intSheet = Convert.ToInt32(objRange.Value); 

       for (int i = 0; i < intSheet; i++) 
       { 
        objRange = (Microsoft.Office.Interop.Excel.Range)xlWorkSheet.Cells[6, 3+i ]; 
        if (objRange.Value != null) 
        { 
         lsvSelectedQ.Items.Add(Convert.ToString(objRange.Value)); 
        } 
       } 
      }   

      ReleaseMyExcelsObjects(xlApp, xlWorkBook, xlWorkSheet);   
     } 

を上記のコードでは、私はタスクバーにExcelのプロセスを実行しているのを取り除くためにReleaseMyExcelsObjectsメソッドを使用しています。あなたが見ることができるように

private void ReleaseMyExcelsObjects(Microsoft.Office.Interop.Excel.Application xlApp, Microsoft.Office.Interop.Excel.Workbook xlWorkBook, Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet) 
     { 
      xlApp.DisplayAlerts = false; 
      xlWorkBook.Save(); 
      xlWorkBook.Close(); 
      xlApp.DisplayAlerts = false; 
      xlApp.Quit(); 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkSheet); 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook); 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp); 
      xlWorkSheet = null; 
      xlWorkBook = null; 
      xlApp = null; 
      GC.Collect(); 
     } 

私はSelectedIndexChanged上でExcelを開いて、私はまた、ReleaseMyExcelsObjects()メソッドを介してプロセスをクローズしようとしていますし、それが生成された最初のExcelのプロセスを除いて動作します。つまり、イベントが起動され、Excelプロセスが開始され、ReleaseMyExcelsObjects()は終了しませんが、もう一度SelectedIndexChangedが起動され、別のExcelプロセスが開始されます。今回はReleaseMyExcelsObjects()がこの2番目のExcelプロセスを終了します。しかし、最初にSelectedIndexChangedイベントが発生したときに開始された最初のExcelプロセスは決して閉じられません。

EDIT:

私は仕事を得ている答え自分を掲載しています。しかし、誰かがより良い解決策を思いつく場合に備えて、この質問を開いておくつもりです。 アプリケーションがを終了すると、あなたのC#の私の理解から

答えて

0

は、からReleaseComObjectは、Excelアプリケーションを閉じます。したがって、FillSelectedItems()を呼び出すたびに、新しいExcelプロセスがタスクバーに表示され、C#アプリケーションを終了するまで閉じることはありません。

EDIT:try、catch、finallyを使用することをお勧めします。これは主に、アプリケーションが例外に実行されるとプログラムが正常に終了しないことと、それは、タスクバーに残っているExcelのプロセスになります前に述べたように、あなたはこの悩まされている場合、

string filepath = string.Empty; 
     string reportname = lblreportname.Text; 
     filepath = Application.StartupPath + "\\StandardReports\\" + reportname + ".xls"; 

     Microsoft.Office.Interop.Excel.Application xlApp; 
     Microsoft.Office.Interop.Excel.Workbook xlWorkBook; 
     Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet; 
     object misValue = System.Reflection.Missing.Value; 

     xlApp = new Microsoft.Office.Interop.Excel.Application(); 
     xlWorkBook = xlApp.Workbooks.Open(filepath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0); 
     List<string> WorksheetList = new List<string>(); 

     try 
     { 
      //Your code 
     } 
     catch (Exception ex) { MessageBox.Show(string.Format("Error: {0}", ex.Message)); } 
     finally 
     { 
      xlWorkBook.Close(false, filepath, null); 
      Marshal.ReleaseComObject(xlWorkBook); 
     } 

正直なところ(と手動オープンはエクセルのファイルを言ったとき、それはあなたを教えてくれます、最後には、バージョンblablablaを回復しました)代替ライブラリとして、EPPlusまたはExcelDataReader(これはExcelスプレッドシートを読むためのもの)を使用することをお勧めします。さもなければ、あなたが追加するreleaseComObjectsやgarbagecollectorsが何個であっても、あなたはこの問題を取り除かないと信じています。

EDIT 2:もちろん、これを一周する別の方法は、ExcelのプロセスIDを検索し、それを殺すことです。私がこれをお勧めしなかった理由は、このアプリケーションを実行しているユーザーがすでにコンピュータ上で別のExcelプロセスを実行している場合、そのインスタンスを強制終了する可能性があるからです。

[System.Runtime.InteropServices.DllImport("user32.dll")] 
     static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); 

     public static Process GetExcelProcess(Microsoft.Office.Interop.Excel.Application excelApp) 
     { 
      int id; 
      GetWindowThreadProcessId(excelApp.Hwnd, out id); 
      return Process.GetProcessById(id); 
     } 

から撮影classobj.GetExcelProcess(xlApp).Kill();

としてそれを使用します:

+0

しかし、上記のコードは、Excelアプリケーションを閉じている各と毎回 'FillSelectedItems() 'が呼び出されます。最初の時間を除く毎回。 – Arbaaz

+0

これは終了呼び出しを行いますが、C#アプリケーションが終了するまで適用されません。FillSelectedItems()を複数回呼び出すことで、タスクバーでチェックすることができます。各コールの後に新しい「Excel」プロセスが表示されます。 – Innat3

+0

'FillSelectedItems()'が呼び出され、Excelプロセスのインスタンスが開始されるたびに。イベントが3回発生した場合、タスクマネージャには3つのExcelプロセスが存在しますが、ReleaseMyExcelsObjectsは毎回新しいインスタンスを閉じます。初めての場合を除きます。 (アプリケーションを終了する必要はありません) – Arbaaz

関連する問題