如何清理创建另一个Excel文件的Excel加载项的COM对象?

时间:2017-07-11 21:02:29

标签: c# excel vsto excel-interop

我创建了一个excel加载项,用于处理活动工作表并打开另一个excel应用程序并写入另一个工作表。程序完成后我不想关闭excel,因为这取决于用户。当我的程序运行时,我可以在任务管理器中看到EXCEL.exe,当它完成后,我仍然可以看到它,这就是我的期望,当我关闭EXCEL时,它会消失,但我仍然不知道是否我应该调用ReleaseComObject以及调用它的变量和时间。这是我目前的代码:

public class ProcessExcel {
 Worksheet activeSheet;

ProcessExcel_Click(object sender, EventArgs e)
{
   //Do I need to break these into variables and/or do I need to dispose of them?
    var addIn = Globals.ThisAddIn;
    var application = addIn.Application;
    var workbook = application.ActiveWorkbook;

activeSheet = workbook.ActiveSheet;

    var processor= new Processor(activeSheet, _bank);

            var processedCells = processor.Process();

            CreateExcelFile();

            GenerateOutput(processor, processedCells);
}

  private void CreateExcelFile()
        {

            var xlApp = new Microsoft.Office.Interop.Excel.Application();


            if (xlApp == null)
            {
                MessageBox.Show("EXCEL could not be started");
                return;
            }

            xlApp.Visible = true;

            var workbooks = xlApp.Workbooks;

            var wb = workbooks.Add();
            xlApp.DefaultSaveFormat = xlFileFormat;

            var worksheets = wb.Worksheets;

            activeSheet = worksheets.Add();
            activeSheet.Name = "Output";


            if (activeSheet == null)
            {
                MessageBox.Show("Worksheet could not be created");
                return;
            }

            var outputSheetColumns = activeSheet.Columns;

            foreach (var item in data.Columns)
            {
                if (item.TargetDataType != null)
                {
                    if (item.TargetDataType.ToLower() == DataType.Text.ToLower())
                    {
                        outputSheetColumns[item.TargetColumnNumber].Numberformat = NumberFormat.Text;
                    }
                }

            }


        }

  private void GenerateOutput(Processor processor, ProcessedCells processedCells)
    {
        var cells = activeSheet.Cells;

        if (data.IncludeHeader)
        {
            processor.SetHeaders(activeSheet);
        }

        foreach (var cell in processedCells.ValidCells)
        {
            var currentCell = cells[cell.RowNumber, cell.ColumnNumber];
            currentCell.Value2 = cell.Value;
        }
    }
}

从上面可以看出,我正在尝试(我认为)使用所有com对象的变量并避免两个点。我确实有以下方法进行清理,但不确定使用它的对象以及何时:

 private void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            obj = null;
            MessageBox.Show("Unable to release the Object " + ex.ToString());
        }
        finally
        {
            GC.Collect();
        }
    }

我看到ReleaseComObject可能没有必要,我可以致电:

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

如果用户负责关闭excel应用程序,上述是否必要?

2 个答案:

答案 0 :(得分:0)

不幸的是,一个有效的解决方案就是杀死进程

System.Diagnostics.Process pro = ExcelProcess.GetExcelProcess(ExcelApp);
pro.Kill();

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

public static System.Diagnostics.Process GetExcelProcess(oExcel.Application excelApp)
{
    int id;
    GetWindowThreadProcessId(excelApp.Hwnd, out id);
    return System.Diagnostics.Process.GetProcessById(id);
}

答案 1 :(得分:0)

使用内置于interop中的函数退出Workbook对象。

using Excel = Microsoft.Office.Interop.Excel; // skip a lot of redundant typing

// declare application/workbook/worksheet objects
Excel.Application applicationObject = new Excel.Application();
Excel.Workbook workbookObject;
Excel.Worksheet worksheetObject;


workbookObject = applicationObject.Open(/* lot of parameters go here */);
worksheetObject = workbookObject.Sheets["SheetName"];
DoThings(worksheetObject);

// finished working with sheet, time to close it
workbookObject.SaveAs(/* necessary parameters */);
workbookObject.Close(/* necessary parameters */);

调用Workbook.Close()方法后,它将结束您通过打开

创建的进程