C# 如何为创建另一个Excel文件的Excel加载项清理COM对象?
我创建了一个excel加载项,用于处理活动工作表并打开另一个excel应用程序并写入另一个工作表。我不想在程序完成时关闭excel,因为这将取决于用户。当我的程序运行时,我可以在任务管理器中看到EXCEL.exe,当它完成时,我仍然可以看到它,这是我所期望的,当我关闭EXCEL时,它消失了,但我仍然不知道我是否应该调用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;
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应用程序保持打开状态。如果不关闭它,它应该保持打开状态。但是如果我杀死进程,它不会关闭吗?