为什么Microsoft.Office.Interop.Excel.Application.Quit()离开后台进程运行?
Why does Microsoft.Office.Interop.Excel.Application.Quit() leave the background process running?
以下代码离开 Microsoft Excel 后台进程 运行,直到我的程序退出:
var excelApplication = new Application();
var workbooks = excelApplication.Workbooks;
var workbook = excelApplication.Workbooks.Open(file.FullName);
workbook.Close();
excelApplication.Workbooks.Close();
excelApplication.Quit();
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApplication);
为什么?我错过了什么?
这是 Office 应用程序中广泛存在的问题。所有 Excel add-ins/automation 应用程序都应在不再需要时系统地释放对 Excel 对象的引用。未能系统地释放对 Excel 对象的引用可能会导致 Microsoft Office Excel 无法正常关闭。有关详细信息,请参阅 Systematically Releasing Objects。它与 Outlook 相关,但相同的原理可以应用于所有 Office 应用程序。
使用完System.Runtime.InteropServices.Marshal.ReleaseComObject释放一个Excel对象。然后在 Visual Basic 中将变量设置为 Nothing(在 C# 中为 null)以释放对该对象的引用。
知道了!
application.Workbooks != application.Workbooks
此 属性 不公开变量,它生成一个值。所以每次我访问工作簿时 属性 我都会创建一个新的 COM 对象。
我修复了代码,一切正常。谢谢大家。
var excelApplication = new Application();
var workbooks = excelApplication.Workbooks;
var workbook = workbooks.Open(pathToExcelWorkbook); // Fixed
workbook.Close();
workbooks.Close();
excelApplication.Quit();
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApplication);
这样做是错误的,但这是解决问题的最简单方法:
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
private Application _excelApp;
private Workbook _excelWorkBook;
private Worksheet _excelSheet;
private void CloseExcelApp()
{
int hWnd = _excelApp.Application.Hwnd;
uint processID;
GetWindowThreadProcessId((IntPtr)hWnd, out processID);
Process.GetProcessById((int)processID).Kill();
_excelWorkBook = null;
_excelApp = null;
_excelSheet = null;
}
您只需要在需要使用它时初始化所有未初始化的变量,并在需要关闭应用程序时调用 CloseExcelApp()。
以下代码离开 Microsoft Excel 后台进程 运行,直到我的程序退出:
var excelApplication = new Application();
var workbooks = excelApplication.Workbooks;
var workbook = excelApplication.Workbooks.Open(file.FullName);
workbook.Close();
excelApplication.Workbooks.Close();
excelApplication.Quit();
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApplication);
为什么?我错过了什么?
这是 Office 应用程序中广泛存在的问题。所有 Excel add-ins/automation 应用程序都应在不再需要时系统地释放对 Excel 对象的引用。未能系统地释放对 Excel 对象的引用可能会导致 Microsoft Office Excel 无法正常关闭。有关详细信息,请参阅 Systematically Releasing Objects。它与 Outlook 相关,但相同的原理可以应用于所有 Office 应用程序。
使用完System.Runtime.InteropServices.Marshal.ReleaseComObject释放一个Excel对象。然后在 Visual Basic 中将变量设置为 Nothing(在 C# 中为 null)以释放对该对象的引用。
知道了!
application.Workbooks != application.Workbooks
此 属性 不公开变量,它生成一个值。所以每次我访问工作簿时 属性 我都会创建一个新的 COM 对象。
我修复了代码,一切正常。谢谢大家。
var excelApplication = new Application();
var workbooks = excelApplication.Workbooks;
var workbook = workbooks.Open(pathToExcelWorkbook); // Fixed
workbook.Close();
workbooks.Close();
excelApplication.Quit();
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApplication);
这样做是错误的,但这是解决问题的最简单方法:
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
private Application _excelApp;
private Workbook _excelWorkBook;
private Worksheet _excelSheet;
private void CloseExcelApp()
{
int hWnd = _excelApp.Application.Hwnd;
uint processID;
GetWindowThreadProcessId((IntPtr)hWnd, out processID);
Process.GetProcessById((int)processID).Kill();
_excelWorkBook = null;
_excelApp = null;
_excelSheet = null;
}
您只需要在需要使用它时初始化所有未初始化的变量,并在需要关闭应用程序时调用 CloseExcelApp()。