問題:
當用如下代碼操作完Excel,雖然調用了Application的Quit()方法,但發現Excel進程並沒退出。
object missing = System.Reflection.Missing .Value;
Application app = new Application();
app.Visible = false ;
app.UserControl = true ;
Workbook wb = app.Workbooks.Open(path, missing, true , missing, missing, missing, missing,
missing, missing, true , missing, missing, missing, missing, missing);
Worksheet ws = (Worksheet )wb.Worksheets.get_Item(1);
Console .WriteLine(ws.Cells[2,1].Value);
ws.Close();
ws = null;
app.Quit();
app = null;
結果:
原因:
When Visual Studio .NET calls a COM object from managed code, it automatically creates a Runtime Callable Wrapper (RCW). The RCW marshals calls between the .NET application and the COM object. The RCW keeps a reference count on the COM object.
Therefore, if all references have not been released on the RCW, the COM object does not quit.
解決方案:
1、爲每一個對象定義一個變量。
例如:
把這段代碼
Workbook wb = wbs.Open(path, missing, true , missing, missing, missing, missing,
missing, missing, true , missing, missing, missing, missing, missing);
改爲
Workbooks wbs = app.Workbooks;
Workbook wb = wbs.Open(path, missing, true , missing, missing, missing, missing,
missing, missing, true , missing, missing, missing, missing, missing);
2、當使用完com對象對其循環調用System.Runtime.InteropServices.Marshal.ReleaseComObject 直到返回值爲0
3、設置變量位null
4、調用Quit方法通知服務器關閉
5、調用GC .Collect();
最終:
把上邊的代碼修改爲:
public static void ExcelRead(string path)
{
object missing = System.Reflection.Missing.Value;
Application app = new Application();
app.Visible = false;
app.UserControl = true;
Workbooks wbs = app.Workbooks;
Workbook wb = wbs.Open(path, missing, true, missing, missing, missing, missing,
missing, missing, true, missing, missing, missing, missing, missing);
Sheets wss = wb.Worksheets;
Worksheet ws = (Worksheet)wss.get_Item(1);
Console.WriteLine(ws.Cells[2,1].Value);
NAR(ws);
ws = null;
NAR(wss);
wss = null;
wb.Close();
NAR(wb);
wb = null;
wbs.Close();
NAR(wbs);
wbs = null;
app.Quit();
NAR(app);
app = null;
GC.Collect();
}
private static void NAR(object o)
{
try
{
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
}
catch
{ }
finally
{
o = null;
}
}
結果能正常關閉Excel進程。