【问题标题】:Microsoft.Interop object won't quit or "release"Microsoft.Interop 对象不会退出或“释放”
【发布时间】:2012-03-06 07:05:36
【问题描述】:

每次我运行这段代码时,对象都不会关闭。我仍然在任务管理器中运行了一个 excel.exe。即使我设置了 objects = null,仍然没有。我什至尝试过使用对象 .Quit() 方法。

我在这里做错了什么?

    private bool ValidateQM()
    {
        //setup the objects
        Excel.Application oXL = null;
        Excel.Workbook oWB = null;
        Excel.Worksheet oSheet = null;
        int hWnd = 0;

        try
        {

            //Start Excel and get Application object.
            oXL = new Excel.Application();
            hWnd = oXL.Application.Hwnd;
            oXL.Visible = false;

            //Open the workbook.
            oWB = oXL.Workbooks.Open(workingForm, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",true, false, 0, true, false, false);

            //Get the Worksheet
            oSheet = oWB.Worksheets[1];

            //Check the date values

            string mydatetime = oSheet.Cells[5, 33].Text.ToString() + " " + oSheet.Cells[7, 33].Text.ToString();
            string dateofscore = oSheet.Cells[3, 12].Text.ToString();

            DateTime.Parse(mydatetime); //make my string a real boy
            DateTime.Parse(dateofscore);

            // Cleanup 
            GC.Collect();
            GC.WaitForPendingFinalizers();

            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oSheet);

            //oWB.Close();
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oWB);

            //oXL.Quit();
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oXL);

            return true;
        }

【问题讨论】:

  • 代码很糟糕,混合了自动和手动内存管理,最终两者都没有。但它不起作用,因为您正在调试 Debug 构建。 Cells[,] 索引器生成了隐藏的对象引用。当您调试时,它们使 Excel 保持活动状态,直到方法结束。它将在没有调试器的情况下在发布版本中工作。将大部分代码移到单独的方法中以改善结果。

标签: c# object excel-interop


【解决方案1】:

你不违反hWnd = oXL.Application.Hwnd 行中的“不要使用 2 个点”规则吗?有关更多信息,请参阅Excel interop libraries incompatible with ASP.NET?

【讨论】:

    【解决方案2】:

    当您调用 GC.Collect() 时,oXL 和 oWB 对象仍在范围内,因此对它们有活动的引用。结果, GC.Collect() 不会触及它们。如果要确保它们被垃圾收集,请将它们设置为 null 以便在调用 GC.Collect() 时没有活动引用。此外,您可能希望在活动工作簿上调用 Close(),在 Excel 应用程序上调用 Quit()。您还可以使用大括号 { } 将所有内容放在自己的范围内,以便它们一起超出范围。

            // Cleanup 
            oWB.Close(false);
            oWB = null;
            oXL.Quit();
            oXL = null;
            hWnd = null;
    #if (DEBUG_SPEED_UP_GC)
            GC.Collect();
            GC.WaitForPendingFinalizers();
    #endif
    

    编辑:请注意,手动调用垃圾回收是个坏主意。我假设你这样做只是为了调试目的,以便在 GC 发生时加快速度,所以我添加了#if。

    【讨论】:

    • 或者更好的是,不要手动调用垃圾收集,防止出现大量棘手的错误。
    • @Cody,我以为他只是出于调试目的调用垃圾收集。同意在实时应用程序中这样做对错误和性能都是不利的。
    • 为了调试目的调用垃圾回收的理由并不多,否则你永远不会这样做。事实上,我想不出任何(但只要我说没有,就会有人想出一些模糊的边缘案例作为回应)。关键是,这并不能真正解决这个问题。此外,您的回答并没有表明您真的不应该这样做,我认为这是一个错误。
    【解决方案3】:

    我将假设未引发异常,并且您未显示的 catch 处理程序不会对您的问题进行任何恶意操作。

    我什至尝试过使用对象的Quit 方法

    除非有针对此的一些书面建议,否则我不明白您为什么不总是致电 Quit 以表明您已完成应用程序。

    //Start Excel and get Application object. oXL = new
    Excel.Application();
    hWnd = oXL.Application.Hwnd;
    oXL.Visible = false;
    

    别担心您要更改不属于您的窗口的可见性,如果 Excel 在退出时显示警告会怎样?在父窗口上将Visible 设置为false 会使用户无法看到它。

    为了调试,尽量不要隐藏窗口。

    here 提供了一些信息,说明您可以采取哪些措施来防止 Excel 产生需要交互注意的警告。它的基本要点:

    DisplayAlerts = false
    AskToUpdateLinks = false
    AlertBeforeOverwriting = false
    Interactive = false
    Visible = false
    FeatureInstall = 0 'msoFeatureInstallNone
    

    您正在交互式用户会话中运行您的应用程序,对吗?因为anything else is not supported

    微软目前不推荐也不支持, 无人值守的 Microsoft Office 应用程序自动化, 非交互式客户端应用程序或组件(包括 ASP、 ASP.NET、DCOM 和 NT 服务),因为 Office 可能表现出不稳定 Office 在此环境中运行时出现的行为和/或死锁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多