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

C# 如何为创建另一个Excel文件的Excel加载项清理COM对象?,c#,excel,vsto,excel-interop,C#,Excel,Vsto,Excel Interop,我创建了一个excel加载项,用于处理活动工作表并打开另一个excel应用程序并写入另一个工作表。我不想在程序完成时关闭excel,因为这将取决于用户。当我的程序运行时,我可以在任务管理器中看到EXCEL.exe,当它完成时,我仍然可以看到它,这是我所期望的,当我关闭EXCEL时,它消失了,但我仍然不知道我是否应该调用ReleaseComObject,以及调用它的变量和时间。这是我目前的代码: public class ProcessExcel { Worksheet activeSheet;

我创建了一个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应用程序,是否有必要执行上述操作?

不幸的是,一个糟糕的解决方案是终止进程

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);
}

使用互操作中内置的函数退出工作簿对象

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 */);

调用工作簿.Close()方法后,它将结束您通过打开创建的进程。在我的情况下,当我的应用程序结束时,我希望excel运行,因为我希望用户关闭它。我很好奇,如果我保持excel打开,是否还需要释放内存。这段代码捕获了C#代码excel进程使用的进程ID。它扼杀了这个过程。您可以调用许多excel进程来执行任何操作。这只会杀死附加到ExcelApp对象的进程。但我希望我的C#代码使用的excel应用程序保持打开状态。如果不关闭它,它应该保持打开状态。但是如果我杀死进程,它不会关闭吗?