在 Excel 添加中正确处理 Excel COM 对象
properly disposing of Excel COM object in Excel Add in
好吧,我相信这个问题一定已经被问过一百万次了,所以很抱歉重复,但我不明白为什么在 运行 这个应用程序之后我的任务管理器中仍然有一个 COM 对象.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;
using System.Reflection;
using System.Runtime.InteropServices;
namespace DataDumpTest
{
public partial class DataDumpRibbon
{
private Excel.Application _xlApp = null;
private Excel.Workbook _wb = null;
private Excel.Worksheet _ws = null;
private void DataDumpRibbon_Load(object sender, RibbonUIEventArgs e)
{
}
private void LoadOpenFileDialog()
{
this.openFileDialog1.Filter = "Excel File (*.XLSX) | *.XLSX";
this.openFileDialog1.Title = "Ariel's Special Definition";
this.openFileDialog1.Multiselect = false;
}
private void btnDataDump_Click(object sender, RibbonControlEventArgs e)
{
LoadOpenFileDialog();
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_xlApp = new Excel.Application();
_xlApp.Visible = false;
_xlApp.DisplayAlerts = false;
_xlApp.ScreenUpdating = false;
_wb = _xlApp.Workbooks.Open(openFileDialog1.FileName);
_ws = _wb.Worksheets["Sheet1"];
_ws.UsedRange.Copy(Type.Missing);
// get range to paste into
Excel.Worksheet activeWs = Globals.ThisAddIn.Application.ActiveSheet;
if (activeWs != null)
{
Excel.Range rng = activeWs.Cells[1, 1];
rng.Select();
Globals.ThisAddIn.Application.ActiveSheet.Paste(Type.Missing, Type.Missing);
}
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(_ws);
_wb.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(_wb);
_xlApp.Quit();
Marshal.FinalReleaseComObject(_xlApp);
}
}
}
}
所以我有兴趣处理的 COM 对象是我通过 OpenfileDialog1 打开的 _xlApp、_wb 和 _ws。当我调试它时,我可以在我的任务管理器中看到,当我按下按钮时,另一个 Excel 实例出现并且在我停止调试器之前不会消失。我放出来的时候不应该没了吗?我在这里错过了什么吗?
Ps。这只是一个简单的 copy/paste 从一个 excel 到另一个 excel ,但我想确保在我继续这个应用程序的其余部分之前我在这里得到它。
嗯,尝试使用:
Marshal.ReleaseComObject(YourComApp);
如果还是不行,请尝试在 运行 Marshal 之后取消 COM 对象。我知道在 powershell 中我也必须转储变量。
好吧,我相信这个问题一定已经被问过一百万次了,所以很抱歉重复,但我不明白为什么在 运行 这个应用程序之后我的任务管理器中仍然有一个 COM 对象.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;
using System.Reflection;
using System.Runtime.InteropServices;
namespace DataDumpTest
{
public partial class DataDumpRibbon
{
private Excel.Application _xlApp = null;
private Excel.Workbook _wb = null;
private Excel.Worksheet _ws = null;
private void DataDumpRibbon_Load(object sender, RibbonUIEventArgs e)
{
}
private void LoadOpenFileDialog()
{
this.openFileDialog1.Filter = "Excel File (*.XLSX) | *.XLSX";
this.openFileDialog1.Title = "Ariel's Special Definition";
this.openFileDialog1.Multiselect = false;
}
private void btnDataDump_Click(object sender, RibbonControlEventArgs e)
{
LoadOpenFileDialog();
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
_xlApp = new Excel.Application();
_xlApp.Visible = false;
_xlApp.DisplayAlerts = false;
_xlApp.ScreenUpdating = false;
_wb = _xlApp.Workbooks.Open(openFileDialog1.FileName);
_ws = _wb.Worksheets["Sheet1"];
_ws.UsedRange.Copy(Type.Missing);
// get range to paste into
Excel.Worksheet activeWs = Globals.ThisAddIn.Application.ActiveSheet;
if (activeWs != null)
{
Excel.Range rng = activeWs.Cells[1, 1];
rng.Select();
Globals.ThisAddIn.Application.ActiveSheet.Paste(Type.Missing, Type.Missing);
}
// clean up
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(_ws);
_wb.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(_wb);
_xlApp.Quit();
Marshal.FinalReleaseComObject(_xlApp);
}
}
}
}
所以我有兴趣处理的 COM 对象是我通过 OpenfileDialog1 打开的 _xlApp、_wb 和 _ws。当我调试它时,我可以在我的任务管理器中看到,当我按下按钮时,另一个 Excel 实例出现并且在我停止调试器之前不会消失。我放出来的时候不应该没了吗?我在这里错过了什么吗?
Ps。这只是一个简单的 copy/paste 从一个 excel 到另一个 excel ,但我想确保在我继续这个应用程序的其余部分之前我在这里得到它。
嗯,尝试使用:
Marshal.ReleaseComObject(YourComApp);
如果还是不行,请尝试在 运行 Marshal 之后取消 COM 对象。我知道在 powershell 中我也必须转储变量。