Excel process doesn't get closed

一世执手 提交于 2019-12-01 19:30:33

You may have to go ridiculously explicit:

excelWorkbook.Close (false, System.Reflection.Missing.Value,System.Reflection.Missing.Value) ;   
excelWorkbooks.Close();  
excelApp.Quit();  
Marshal.ReleaseComObject(excelWorksheet);  
Marshal.ReleaseComObject(excelSheets);  
Marshal.ReleaseComObject(excelWorkbooks);  
Marshal.ReleaseComObject(excelWorkbook);  
Marshal.ReleaseComObject(excelApp);  
excelWorksheet = null;  
excelSheets = null;  
excelWorkbooks = null;  
excelWorkbook = null;  
excelApp = null;  
GC.GetTotalMemory(false);  
GC.Collect();  
GC.WaitForPendingFinalizers();  
GC.Collect();  
GC.GetTotalMemory(true);  

I've encountered situations where even that did not do it. I resorted to hunting down the Excel process and called Kill() on it.

Release your Excel objects in a finally block, in case of exceptions.

try
{
...
}
catch
{
...
}
finally
{
  ReleaseObject(XLS);
  ReleaseObject(XLW);
  ReleaseObject(XLA);
}

First suggestion: http://code.google.com/p/excellibrary This is a great library that I have used with a lot of success.

Second suggestion: If you absolutely MUST close Excel

/// <summary>
/// Gets all currently running instances of Excel, so we don't kill active windows.
/// </summary>
private void GetInstancesToSave()
{
    if (_instancesToSaveList != null)
    {
        _instancesToSaveList.Clear();
    }
    _instancesToSaveList = Process.GetProcesses().ToList<Process>();
    _instancesToSaveList = _instancesToSaveList.FindAll(proc => proc.ProcessName == "EXCEL");
}

/// <summary>
/// Kills any instances of Excel that were created by the program.
/// </summary>
/// <param name="zInstancesToSave">Instances that were not </param>
private static void KillExcel(List<Process> zInstancesToSave)
{
    List<Process> xProcesslist = Process.GetProcesses().ToList<Process>();
    xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL");
    foreach (Process xTheprocess in xProcesslist)//read through all running programs
    {
        bool killit = true;
        foreach (Process proc in zInstancesToSave)//read through all running programs
        {
            if (xTheprocess.Id == proc.Id)
            {
                killit = false;
            }
        }
        if (killit)
        {
            xTheprocess.Kill();
        }
    }
}

You can use these 2 methods to keep track of which instances of excel are running when you start and then find any instances of Excel that your app opened and then kill them. It's certainly not a great solution but sometimes you just have to bite the bullet.

If you don't care about prior instances you can also just do:

/// <summary>
/// Kills any instances of Excel that were created by the program.
/// </summary>
/// <param name="zInstancesToSave">Instances that were not </param>
private static void KillExcel(List<Process> zInstancesToSave)
{
    List<Process> xProcesslist = Process.GetProcesses().ToList<Process>();
    xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL");
    foreach(Proc process in xProcesslist)
    {
        process.Kill();
    }
}

I would look into using EPPlus from Code Plex.
This example shows how to read data. You are always better on a server going this route - only issue is if you need call formulas - then this approach will not work.
Most of your code will be very similar to your current code, so I would estimate a few hours for moving to this library.

In my case, the Excel add-in lived in a separate AppDomain that I had created earlier on but when the Add-in was unloaded, I never called:

childDomain.Unload();

Once called, the Excel Zombie process was no longer there...

In addition to the above solutions and here is my LOGICALsolution. I was thinking why do I have so many EXCEL.EXE applications and handled this way. Here i am checking for conditions while creating New Excel application. if (_masterApp == null) _masterApp = new EXCEL.Application(); Only create New Instances of Excel application if the variable you want to create is Null, else reassign the existing variable.

and Use the Solutions mentioned in this blog to CLOSE the _masterApp.

Benefits: This way you will only close the EXCEL application you opened through Solution and not close Manually opened Excel Application.

Look at this link

Kill Process Excel C#

Thanks to KD7 for the solution.

One minor modification is that if your excelapp is not visible your mainwindowtitle will be blank. eg. ""

private void KillSpecificExcelFileProcess(string excelFileName)
    {
        var processes = from p in Process.GetProcessesByName("EXCEL")
                        select p;

        foreach (var process in processes)
        {
            MessageBox.Show(process.MainWindowTitle);
            if (process.MainWindowTitle == excelFileName)
            {

            process.Kill();
            }
        }
    }

and to kill all zombie excel background process'

KillSpecificExcelFileProcess("");

This gave me no end of trouble in solving so I will be posting it on each zombie excel process thread.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!