安全处置在C#中的Excel互操作的对象?
我工作的一个WinForms C#Visual Studio 2008的应用程序。应用会谈Excel文件和我使用的Microsoft.Office.Interop.Excel;
来做到这一点。
i am working on a winforms c# visual studio 2008 application. the app talks to excel files and i am using Microsoft.Office.Interop.Excel;
to do this.
我想知道我可以确保该对象被释放,即使有错误?
i would like to know how can i make sure that the objects are released even when there is an error?
这是我的code:
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);
range = xlWorkSheet.UsedRange;
/*
for (rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
{
for (cCnt = 1; cCnt <= range.Columns.Count; cCnt++)
{
str = (string)(range.Cells[rCnt, cCnt] as Excel.Range).Value2;
MessageBox.Show(str);
}
}
*/
xlWorkSheet..EntireRow.Delete(Excel.XLDirection.xlUp)
xlWorkBook.SaveAs(xlWorkBook.Path + @"\XMLCopy.xls", Excel.XlFileFormat.xlXMLSpreadsheet, Type.Missing, Type.Missing,
false, false, Excel.XlSaveAsAccessMode.xlNoChange,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
xlWorkBook.Close(true, null, null);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
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();
}
}
我怎样才能确保即使我得到一个错误后,该工作簿打开,我一定要处置的对象:
how can i make sure that even if i get an error after the workbook opened, that i make sure to dispose of the objects:
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range range;
在换句话说不管是什么,我需要以下行来运行
In other words no matter what i need the following lines to run
xlWorkBook.Close(true, null, null);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
请注意,我已经尝试过这个问题,以及,导致同样的问题。
please note that i have tried this as well, resulting in the same issue
xlWorkBook.Close(false, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
xlApp.Quit();
Marshal.ReleaseComObject(xlWorkSheet);
Marshal.ReleaseComObject(xlWorkBook);
Marshal.ReleaseComObject(xlApp);
xlWorkSheet = null;
xlWorkBook = null;
xlApp = null;
GC.GetTotalMemory(false);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
和我这样做,以及:
GC.Collect() ;
GC.WaitForPendingFinalizers();
GC.Collect() ;
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(xlWorkSheet);
xlWorkBook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(xlWorkBook);
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
在这一点上,我不认为这是可以从Visual Studio 2008中关闭Excel它必须是一个错误或东西,但我试过在这前20名的网站,并得到同样的结果:Excel是打开两个实例出于某种原因,当我做垃圾回收等。(或没有)它关闭只是一个实例。
at this point i do not think it's possible to close excel from visual studio 2008. it must be a bug or something, but i've tried the top 20 websites on this and getting the same result: excel is opening two instances for some reason and when i do the garbage collection etc.. (or not) it closes just ONE instance.
当我尝试打开该文件,它说有错误,或者是腐败的。
when i try to open the file, it says there's an error or it's corrupt.
当我去任务管理器和杀Excel进程,该文件将没有问题打开。]
when i go to task manager and kill the excel process, the file will open without problems.]
是有办法与2008年的Visual Studio关闭Excel?如果是的话,能否请您为我提供指导或到一个解决方案
is there a way to close excel with visual studio 2008? if so, can you please provide me with guidance or a solution to this
首先,我将present修改 releaseObject
,然后我会提供一个模式来使用吧。
First I will present a modified releaseObject
, and then I will provide a pattern to use it.
using Marshal = System.Runtime.InteropServices.Marshal;
private void releaseObject(ref object obj) // note ref!
{
// Do not catch an exception from this.
// You may want to remove these guards depending on
// what you think the semantics should be.
if (obj != null && Marshal.IsComObject(obj)) {
Marshal.ReleaseComObject(obj);
}
// Since passed "by ref" this assingment will be useful
// (It was not useful in the original, and neither was the
// GC.Collect.)
obj = null;
}
现在,一个模式来使用:
Now, a pattern to use:
private void button1_Click(object sender, EventArgs e)
{
// Declare. Assign a value to avoid a compiler error.
Excel.Application xlApp = null;
Excel.Workbook xlWorkBook = null;
Excel.Worksheet xlWorkSheet = null;
try {
// Initialize
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);
// If the cast fails this like could "leak" a COM RCW
// Since this "should never happen" I wouldn't worry about it.
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
...
} finally {
// Release all COM RCWs.
// The "releaseObject" will just "do nothing" if null is passed,
// so no need to check to find out which need to be released.
// The "finally" is run in all cases, even if there was an exception
// in the "try".
// Note: passing "by ref" so afterwords "xlWorkSheet" will
// evaluate to null. See "releaseObject".
releaseObject(ref xlWorkSheet);
releaseObject(ref xlWorkBook);
// The Quit is done in the finally because we always
// want to quit. It is no different than releasing RCWs.
if (xlApp != null) {
xlApp.Quit();
}
releaseObject(ref xlApp);
}
}
这简单的方法可以扩展/嵌套在大多数情况下。我使用实现IDisposable,使这个任务更容易定制的包装类。
This simple approach can be extended/nested over most situations. I use a custom wrapper class that implements IDisposable to make this task easier.