Excel流程未关闭

时间:2013-08-09 19:33:51

标签: c# winforms excel

我有这个C#程序永远不会关闭Excel进程。基本上,它查找字符串在Excel中的范围中出现的实例数。我尝试了各种各样的东西,但它没有用。有一个Form调用此方法,但这不应该更改进程未关闭的原因。我看过Hans Passant的建议,但都没有。

编辑:我尝试了上面提到的东西但它仍然无法关闭。这是我更新的代码。 编辑:尝试整个Process.Kill(),它的工作原理,但它似乎是一个应该工作的东西的黑客攻击。

public class CompareHelper
{
    // Define Variables
    Excel.Application excelApp = null;
    Excel.Workbooks wkbks = null;
    Excel.Workbook wkbk = null;
    Excel.Worksheet wksht = null;
    Dictionary<String, int> map = new Dictionary<String, int>();

    // Compare columns
    public void GetCounts(string startrow, string endrow, string columnsin, System.Windows.Forms.TextBox results, string excelFile)
    {
        results.Text = "";

        try
        {
            // Create an instance of Microsoft Excel and make it invisible
            excelApp = new Excel.Application();
            excelApp.Visible = false;

            // open a Workbook and get the active Worksheet
            wkbks = excelApp.Workbooks;
            wkbk = wkbks.Open(excelFile, Type.Missing, true);
            wksht = wkbk.ActiveSheet;
            ...

        }
        catch
        {
            throw;
        }
        finally
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();

            if (wksht != null)
            {
                //wksht.Delete();
                Marshal.FinalReleaseComObject(wksht);
                wksht = null;
            }

            if (wkbks != null)
            {
                //wkbks.Close();
                Marshal.FinalReleaseComObject(wkbks);
                wkbks = null;
            }

            if (wkbk != null)
            {
                excelApp.DisplayAlerts = false;
                wkbk.Close(false, Type.Missing, Type.Missing);
                Marshal.FinalReleaseComObject(wkbk);
                wkbk = null;
            }

            if (excelApp != null)
            {
                excelApp.Quit();
                Marshal.FinalReleaseComObject(excelApp);
                excelApp = null;
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers();

            /*
            Process[] processes = Process.GetProcessesByName("EXCEL");
            foreach (Process p in processes)
            {
                p.Kill();
            }
            */
        }
    }
}

3 个答案:

答案 0 :(得分:3)

这是一个有趣的知识库,关于办公室应用程序在.NET应用程序断开连接后保持打开的主题。

Office application does not quit after automation from Visual Studio .NET client

代码示例都在链接中(对不起vb.net)。基本上它会向您展示如何正确设置和拆除办公室应用程序,以便在您完成它时关闭它。

System.Runtime.InteropServices.Marshal.FinalReleaseComObject是神奇发生的地方。

编辑:您需要为您创建的每个Excel对象调用FinalReleaseComObject。

if (excelWorkSheet1 != null)
{
    Marshal.FinalReleaseComObject(excelWorkSheet1);
    excelWorkSheet1 = null;
}
if (excelWorkbook != null)
{
    Marshal.FinalReleaseComObject(excelWorkbook);
    excelWorkbook = null;
}
if (excelApp != null)
{
    Marshal.FinalReleaseComObject(excelApp);
    excelApp = null;
}

答案 1 :(得分:2)

DotNet仅在释放所有句柄后释放COM对象。我所做的是评论所有内容,然后添加一部分。看它是否发布Excel。如果不符合以下规则。当它发布时,添加更多代码,直到它不再发布。

1)创建Excel变量时,将所有值设置为null(这样可以避免启动错误)

2)不要在不首先发布变量的情况下重用变量Marshal.FinalReleaseComObject

3)不要加倍(a.b = z)点。 dotNet创建一个临时变量,不会被释放。

c = a.b;
c = z;
Marshal.FinalReleaseComObject(c);

4)释放所有excel变量。越快越好。

5)将其设置回NULL。

将文化设置为“en-US”。有一些错误使Excel崩溃了一些文化。这确保不会。

以下是关于如何构建代码的想法:

        thisThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
        InteropExcel.Application excelApp = null;
        InteropExcel.Workbooks wkbks = null;
        InteropExcel.Workbook wkbk = null;
        try
        {
                excelApp = new InteropExcel.Application();
                wkbks = excelApp.Workbooks;
                wkbk = wkbks.Open(fileName);
...

        }
        catch (Exception ex)
        {
        }

        if (wkbk != null)
        {
            excelApp.DisplayAlerts = false;
            wkbk.Close(false);
            Marshal.FinalReleaseComObject(wkbk);
            wkbk = null;
        }

        if (wkbks != null)
        {
            wkbks.Close();
            Marshal.FinalReleaseComObject(wkbks);
            wkbks = null;
        }

        if (excelApp != null)
        {
            // Close Excel.
            excelApp.Quit();
            Marshal.FinalReleaseComObject(excelApp);
            excelApp = null;
        }

        // Change culture back from en-us to the original culture.
        thisThread.CurrentCulture = originalCulture;    
    }

答案 2 :(得分:1)

我终于把它关闭了。您需要为Workbooks集合添加一个变量,然后按照其他答案中的说明使用FinalReleaseComObject。我猜你使用的每个可能的Excel COM对象都必须这样处理。

try
        {
           // Create an instance of Microsoft Excel and make it invisible
           excelApp = new Excel.Application();
           excelApp.DisplayAlerts = false;
           excelApp.Visible = false;

           // open a Workbook and get the active Worksheet

           excelWorkbooks = excelApp.Workbooks;
           excelWorkbook = excelWorkbooks.Open(excelFile, Type.Missing, true);
           excelWorkSheet1 = excelWorkbook.ActiveSheet;

        }
        catch
        {
           throw;
        }
        finally
        {

           NAR( excelWorkSheet1 );
           excelWorkbook.Close(false, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
           NAR(excelWorkbook);
           NAR(excelWorkbooks);
           excelApp.Quit();
           NAR(excelApp);

        }
     }
     private void NAR(object o)
     {
        try
        {
           System.Runtime.InteropServices.Marshal.FinalReleaseComObject( o );
        }
        catch { }
        finally
        {
           o = null;
        }
     }