为什么Microsoft.Office.Interop.Excel.Application.Quit()会让后台进程运行?

ski*_*are 14 c# excel office-interop excel-interop

以下代码将运行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);
Run Code Online (Sandbox Code Playgroud)

为什么?我错过了什么?

ski*_*are 28

得到它了!

application.Workbooks!= application.Workbooks

此属性不公开变量,它会生成一个值.所以每次我访问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);
Run Code Online (Sandbox Code Playgroud)

  • 嗨@eugene - 你的答案肯定让我朝着正确的方向前进,但我没有发现它具体到足以解决整个问题.如果比较我的两个代码示例中的第3行,您将看到问题是我无法理解Workbooks属性将始终返回一个新对象. (2认同)

Eug*_*iev 7

这是Office应用程序的一个广泛传播的问题.所有Excel加载项/自动化应用程序应在不再需要时系统地释放对Excel对象的引用.未能系统地释放对Excel对象的引用可能会阻止Microsoft Office Excel正常关闭.有关详细信息,请参阅系统释放对象.它与Outlook有关,但相同的原则可以应用于所有Office应用程序.

使用System.Runtime.InteropServices.Marshal.ReleaseComObject释放Excel对象.然后在Visual Basic中将变量设置为Nothing(C#中为null)以释放对该对象的引用.

  • 似乎是一个合理的回应,不知道为什么你被投票 (2认同)
  • 这仍然将该对象保留在任务列表中。将其设置为 NULL 没有帮助(在 C# 中) (2认同)

And*_*rew 6

这是错误的做法,但这是解决问题的最简单方法

    [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;
    }
Run Code Online (Sandbox Code Playgroud)

您只需要在需要使用它时初始化所有未初始化的变量,并在需要关闭应用程序时调用 CloseExcelApp()。