这是(潜在的)问题:
我创建一个COM对象,然后使用'foreach'迭代它返回的集合中的每个元素.我是否需要释放我在集合中迭代的每个元素?(参见下面的代码.)如果是这样的话,我无法想出一种有效地从'finally'语句中释放它的方法,以防万一在项目被操作时出现错误.
有什么建议?
private static void doStuff()
{
ComObjectClass manager = null;
try
{
manager = new ComObjectClass();
foreach (ComObject item in manager.GetCollectionOfItems())
{
Log.Debug(item.Name);
releaseComObject(item); // <-- Do I need this line?
// It isn't in a 'finally' block...
// ...Possible memory leak?
}
}
catch (Exception) { }
finally
{
releaseComObject(manager);
}
}
private static void releaseComObject(object instance)
{
if (instance != null)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(instance);
}
catch
{
/* log potential memory leak */
Log.Debug("Potential memory …
Run Code Online (Sandbox Code Playgroud) 我正在开发一个winforms c#visual studio 2008应用程序.该应用程序与excel文件对话,我正在使用Microsoft.Office.Interop.Excel;
这个.
我想知道即使出现错误,如何确保对象被释放?
这是我的代码:
private void button1_Click(object sender, EventArgs e)
{
string myBigFile="";
OpenFileDialog openFileDialog1 = new OpenFileDialog();
DialogResult result = openFileDialog1.ShowDialog(); // Show the dialog.
if (result == DialogResult.OK) // Test result.
myBigFile=openFileDialog1.FileName;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range range;
string str;
int rCnt = 0;
int cCnt = 0;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Open(myBigFile, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", true, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); …
Run Code Online (Sandbox Code Playgroud) 我正在通过C#尝试Excel自动化.我已经按照微软的所有指示来解决这个问题,但是我仍然在努力放弃Excel的最终引用,以便关闭它并使GC能够收集它.
代码示例如下.当我注释掉包含类似于以下行的代码块时:
Sheet.Cells[iRowCount, 1] = data["fullname"].ToString();
Run Code Online (Sandbox Code Playgroud)
然后文件保存并退出Excel.否则文件将保存,但Excel将作为进程运行.下次运行此代码时,它会创建一个新实例,并最终构建它们.
任何帮助表示赞赏.谢谢.
这是我的代码的准系统:
Excel.Application xl = null;
Excel._Workbook wBook = null;
Excel._Worksheet wSheet = null;
Excel.Range range = null;
object m_objOpt = System.Reflection.Missing.Value;
try
{
// open the template
xl = new Excel.Application();
wBook = (Excel._Workbook)xl.Workbooks.Open(excelTemplatePath + _report.ExcelTemplate, false, false, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt, m_objOpt);
wSheet = (Excel._Worksheet)wBook.ActiveSheet;
int iRowCount = 2;
// enumerate and drop the values straight into the Excel file
while (data.Read())
{
wSheet.Cells[iRowCount, …
Run Code Online (Sandbox Code Playgroud) 使用COM对象考虑以下C#代码.
MyComObject o = new MyComObject;
try
{
var baz = o.Foo.Bar.Baz;
try
{
// do something with baz
}
finally
{
Marshal.ReleaseComObject(baz);
}
}
finally
{
Marshal.ReleaseComObject(o);
}
这将释放COM对象o
和baz
,而不是临时对象returnd的o.Foo
和o.Foo.Bar
.当这些对象拥有大量非托管内存或其他资源时,这可能会导致问题.
一个明显但丑陋的解决方案是,使用try-finally
和更加混乱代码Marshal.ReleaseComObject
.请参阅
C#+ COM Interop,确定性版本
作为一种解决方法,我创建了一个帮助类
class TemporaryComObjects: IDisposable
{
public C T<C>(C comObject)
{
m_objects.Add(comObject);
return comObject;
}
public void Dispose()
{
foreach (object o in m_objects)
Marshal.ReleaseComObject(o);
}
}
用法:
using (TemporaryComObjects t = new TemporaryComObjects())
{ …
Run Code Online (Sandbox Code Playgroud) 我正在开发一个严重依赖多个Microsoft Office产品的应用程序,包括Access,Excel,Word,PowerPoint和Outlook等.在对互操作进行研究时,我发现从VS2010和.NET 4开始,我们感谢不再需要经历PIA的噩梦.
此外,我一直在阅读很多关于正确处理物品的文章,最明智的就是这个.
然而,这篇文章已有5年历史,关于AFAIK这一主题的权威出版物并不多.以下是上述链接的代码示例:
' Cleanup:
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()
Marshal.FinalReleaseComObject(worksheet)
oWB.Close(SaveChanges:=False)
Marshal.FinalReleaseComObject(workbook)
oApp.Quit()
Marshal.FinalReleaseComObject(application)
Run Code Online (Sandbox Code Playgroud)
我想知道的是今天的标准,如果我希望在未来几年支持我的申请,我应该注意什么?
更新:一些可靠文章的链接将受到高度赞赏.顺便说一句,这不是服务器端应用程序.这将在计算机实验室中运行,我们让用户与我们实例化的办公产品进行交互.
发现它: 这篇由三部分组成的文章可能是最接近我期望找到的权威帐户的文章.
我正在尝试将C#与COM Interop库一起使用来打开一组非常繁重的Excel工作簿.我必须使用C#,因为我还需要启动宏,移动一些单元格,并启动我公司使用的自定义excel-add-in.
然后我的程序退出,打开工作簿,每个工作簿都在一个单独的excel实例中.我不希望在程序退出时关闭工作簿.
问题是当我的C#程序退出时,随着时间的推移,excel工作簿逐渐消耗更多的内存,直到他们从原来的500 MB消耗3.5 GB的内存.
我曾经手工打开工作簿,这些工作表从来没有消耗过那么多的记忆.一旦我开始使用C#打开它们,它们就会因极端内存使用而开始破解.我的理论是,不知何故,当我与COM Excel对象交互时,我创建了一个内存泄漏.
以下是我的原始代码:
using Excel = Microsoft.Office.Interop.Excel;
...
excelApp = new Excel.Application();
excelApp.Visible = true;
excelApp.Workbooks.Open(filename, misValue, misValue, misValue, misValue, misValue,
true, misValue, misValue, misValue, misValue, misValue, misValue, misValue, misValue);
excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic;
Run Code Online (Sandbox Code Playgroud)
我读到了你需要如何使用Marshal来释放用途,所以我现在正在尝试以下代码,但没有简单的方法来测试它,除了打开所有工作表并查看它们是否消耗了太多数据.
excelApp = new Excel.Application();
excelApp.Visible = true;
Excel.Workbooks currWorkbooks = excelApp.Workbooks;
Excel.Workbook currWorkbook = currWorkbooks.Open(filename, misValue, misValue, misValue, misValue, misValue,
true, misValue, misValue, misValue, misValue, misValue, misValue, misValue, misValue);
//excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic;
int x = Marshal.ReleaseComObject(currWorkbook);
currWorkbook = null;
int …
Run Code Online (Sandbox Code Playgroud) 可能重复:
如何在C#中正确清理Excel互操作对象
假设ASP.NET Web应用程序在服务器上生成自动Excel报告.处理结束后,我们如何杀死服务器端的Excel.EXE.我故意提出这个,因为我相信垃圾收集器即使在关闭Excel文件后也不会清理Excel可执行文件.
任何指针都会有所帮助?
所有这些问题:
解决了C#在使用后没有正确释放Excel COM对象的问题.解决这个问题主要有两个方向:
有人说过2太繁琐了,你是否忘记在代码中的某些地方忘记遵守这条规则总是存在一些不确定性.仍然1对我来说似乎很脏并且容易出错,我想在有限的环境中试图杀死一个进程可能会引发安全错误.
所以我一直在考虑通过创建另一个模仿Excel对象模型的代理对象模型来解决问题2(对我来说,实现我实际需要的对象就足够了).原则如下:
例:
public class Application
{
private Microsoft.Office.Interop.Excel.Application innerApplication
= new Microsoft.Office.Interop.Excel.Application innerApplication();
~Application()
{
Marshal.ReleaseCOMObject(innerApplication);
innerApplication = null;
}
public Workbooks Workbooks
{
get { return new Workbooks(innerApplication.Workbooks); }
}
}
public class Workbooks
{
private Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks;
Workbooks(Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks)
{
this.innerWorkbooks = innerWorkbooks;
}
~Workbooks()
{
Marshal.ReleaseCOMObject(innerWorkbooks);
innerWorkbooks = null;
}
}
Run Code Online (Sandbox Code Playgroud)
我特别向你提问:
我错过了一个Excel.Application.Quit
或一个Excel.Application.BeforeQuit
事件.有人知道模仿这些事件的解决方法吗?
我通过COM Interop从C#WinForms应用程序访问Excel.给定一个Excel.Application
对象,我该怎么做:
请注意:由于我有一个COM引用Excel.Application
,当Excel被用户"退出"时,Excel进程不会退出.虽然这听起来很矛盾,但事实就是如此.通过"退出"我的意思是用户点击窗口右上角的"退出"或"十字按钮".窗口关闭,文件被卸载,加载项被卸载以及Excel除了我没有任何线索之外做的任何东西.但是我仍然可以使用该Application
对象来"恢复"该过程并使Excel再次可见,尽管这些加载项随后丢失,而且我还不知道还有什么处于未定义状态.
为了摆脱这个问题,我想在一开始就取消退出(想想BeforeQuit
Cancel = true
它是否存在),或者至少在退出Excel时得到通知,这样我就可以释放COM对象并使流程真正退出,下次我再次需要Excel时,我会知道我需要先启动它.
不幸的是,它是一个恶性循环:只要Excel运行,我需要COM对象.因此,在 Excel退出之前,我无法处理它们.另一方面,只要COM对象存在,即使Excel假装退出,进程也不会退出,因此我不能等待进程退出事件或类似事件.
我有一种令人不快的感觉,就是我要把头撞在砖墙上......
在使用Excel Interop与.Net开发一段时间之后,我越来越恼火于发生了多少"奇怪的事情" - 比如我之前发布的这个问题 - 我的问题.
我理解这不是一个直接的问题,更多的是经验的结合,但我确实认为找出人们最大的烦恼/奇怪的事情以及如何克服它们会有所帮助.
这样我就可以找出将来遇到的问题:)
谢谢
c# ×9
excel ×7
interop ×6
com ×4
.net ×3
com-interop ×3
automation ×2
asp.net ×1
dispose ×1
excel-2007 ×1
memory-leaks ×1
ms-office ×1
vb.net ×1