【问题标题】:PowerPoint Launched via C# does not Quit通过 C# 启动的 PowerPoint 不退出
【发布时间】:2010-11-02 03:58:18
【问题描述】:

嘿,我正在通过 C# WinForms 应用程序自动化 PowerPoint 和 Excel;我所做的是从 PowerPoint 中读取幻灯片并将它们保存在 Excel 中,然后退出这两个应用程序。 Excel 成功退出,但 PowerPoints 没有退出。问题是当我第一次转换时它不会退出,但是当我再次转换时它会退出。

这是我的代码

try
{
    PowerPoint.Application ppApp;
    PowerPoint.Presentation ppPres;
    List<Company> companies = new List<Company>();

    ppApp = new PowerPoint.Application();
    ppApp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
    ppApp.WindowState = Microsoft.Office.Interop.PowerPoint.PpWindowState.ppWindowMinimized;

    ppPres = ppApp.Presentations.Open(fileTxtBox.Text,
                                      Microsoft.Office.Core.MsoTriState.msoFalse,
                                      Microsoft.Office.Core.MsoTriState.msoFalse,
                                      Microsoft.Office.Core.MsoTriState.msoTrue);

    int slides = ppPres.Slides.Count;

    for (int slide = 1; slide <= slides; slide++)
    {
        int rows = 1;
        PowerPoint.Cell cell;
        int shape = 1;

        for (; shape < ppPres.Slides[slide].Shapes.Count; shape++)
        {
            if (ppPres.Slides[slide].Shapes[shape].HasTable == Microsoft.Office.Core.MsoTriState.msoTrue)
            {
                cell = ppPres.Slides[slide].Shapes[shape].Table.Cell(1, 1);

                if (cell.Shape.TextFrame.TextRange.Text.Trim().ToLower().Contains("realized"))
                {
                    rows = ppPres.Slides[slide].Shapes[shape].Table.Rows.Count;
                    break;
                }
            }
        }

        Company comp = new Company(rows);
        InitializeCompany(ref comp, ppPres.Slides[slide]);
        companies.Add(comp);
    }

    SaveInExcel(companies);

    ppPres.Close();
    ppPres = null;
    ppApp.Quit();
    ppApp = null;

    return;
}

catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

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

【问题讨论】:

    标签: c# com powerpoint


    【解决方案1】:

    我在 VS2019 中使用 VSTO 来管理 Office-365 应用程序,使用“Application.Quit()”一切正常 - 除了 Powerpoint!

    PP 有时会死机,有时它会在几秒钟内出现很多“ThreadException”直到退出(我猜它真的中止了它的线程)。我已经测试了上面所有的代码和在谷歌中找到的许多其他提示,但没有成功。

    这是一个肮脏的解决方案,但它可以在演示文稿保存后立即关闭 PP。

    但我建议您,我的解决方案是通过自定义 RIBBON GROUP 中按钮的单击事件启动的;否则你将不得不以编程方式“找到” PP 窗口并选择它(将焦点放在它上面)。

    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
    
    SendKeys.Send("%{F4}")
    

    这就是大家...

    【讨论】:

      【解决方案2】:

      这个作品适合我

             var app = new PowerPoint.Application();
                  PowerPoint.Presentations pres = app.Presentations;
                  PowerPoint.Presentation ActivePresentation = pres.Open(fileIn, MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse);
      (...)
                  ActivePresentation.SaveAs(fileOut, PowerPoint.PpSaveAsFileType.ppSaveAsDefault, MsoTriState.msoTrue);
      
                  ActivePresentation.Close();
                  app.Quit();
      

      【讨论】:

        【解决方案3】:

        嗨,伙计们。最近我观察到,从垃圾收集到退出和关闭对象,对我来说没有任何效果。所以我想出了一个替代方案。我的工作完成后我发现了正在运行的进程,然后通过代码将其杀死。

        代码:

         Process[] pros = Process.GetProcesses();
          for (int i = 0; i < pros.Count(); i++)
           {
           if (pros[i].ProcessName.ToLower().Contains("powerpnt"))
                {
                  pros[i].Kill();
                }
           }
        

        【讨论】:

        • 使用这些 InteropServices 压力很大,但这个解决方案很有效,所以谢谢。有趣的是,多年后它仍然有同样的问题/困难。
        【解决方案4】:

        这是描述问题和解决方案的 MSDN 文章

        http://msdn.microsoft.com/en-us/library/aa679807%28office.11%29.aspx

        基本上推荐是做(注意:GC.Collect()的两次迭代

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

        【讨论】:

        • 它也适用于我,但我不明白为什么这两个电话会改变我的生活。
        【解决方案5】:

        关闭 Microsoft Office 应用程序一开始似乎很棘手,但一旦确定了正确的操作顺序,实际上一点也不难。

        可以分两个阶段安全有效地发布您的 MS Office 应用程序:

        (1) 首先释放命名变量中没有引用的所有次要对象。您可以通过调用 GC.Collect() 然后调用 GC.WaitForPendingFinalizers() 来完成此操作。请注意,如果您使用的是 Visual Studio Tools for Office (VSTO),则需要调用这对命令两次,以使 COM 对象成功发布。但是,您没有使用 VSTO,因此调用它们一次就足够了。

        (2) 然后,在您拥有的每个变量上调用Marshall.FinalReleaseComObject(),通过命名变量显式释放您持有的对象。

        请记住将您拥有的所有变量显式释放到 COM 组件。如果您错过了一个,那么您的 MS Office 应用程序将挂起。在您的代码中,您似乎有三个命名变量包含对您的 PowerPoint 应用程序的引用:ppAppppPrescell

        考虑到这一切,我认为您的清理应该如下所示,它在命名空间内或代码文档顶部使用using System.Runtime.InteropServices

        // using System.Runtime.InteropServices
        
        // Cleanup:
        GC.Collect();
        GC.WaitForPendingFinalizers();
        
        Marshal.ReleaseComObject(cell);
        
        ppPres.Close();
        Marshal.ReleaseComObject(ppPres);
        
        ppApp.Quit();
        Marshal.ReleaseComObject(ppApp);
        

        试一试,我认为这应该适合您...(如果没有,您可能需要显示更多代码。)有关更多信息,我将详细说明如何正确发布 Excel在这里申请:

        How to properly clean up Excel interop objects in C#.

        希望这会有所帮助,让我们知道进展如何......

        -- 迈克

        【讨论】:

        • 嘿,迈克,谢谢,但这没有用。我想告诉你的一件事是,当我关闭自己的 WinForm 应用程序时,PowerPoint 也会关闭。
        • 是的,当您关闭 WinForm 时它关闭是正常的,因为当运行时被拆除时,您未能释放的任何对象最终都会被释放。您可以尝试调用 GC.Collect() 和 GC.WaitForPending() 终结器两次。如果您不使用 VSTO,这应该无关紧要,但它不会受到伤害。您需要考虑这里还有哪些其他变量在起作用...(请参阅下一条评论。)
        • 您需要考虑这里还有哪些其他变量在起作用,然后释放它们。例如:(1)任何地方是否有其他静态变量? (2) 您的 InitializeCompany(ref comp, ppPres.Slides[slide]) 调用是做什么的?如果它在您的公司对象中存储了对 PowerPoint 幻灯片的引用,则此调用连同 company.Add(comp) 将创建对 PowerPoint 引用的永久引用。这些必须使用对 Marshal.FinalReleaseComObject() 的调用来切断,否则 PowerPoint 将挂起。我不知道这是否正在发生,但您需要发布 ALL 您的 PowerPoint 参考资料。
        • 底线。将您的办公室代码与您的 Winform 类分开。不要直接从表单的类中调用它。否则 COM 对象会卡在内存中,直到您终止表单。
        【解决方案6】:

        为您的 ppApp 对象调用 Quit() 后,尝试以下操作

        System.Runtime.InteropServices.Marshal.ReleaseComObject(ppApp);
        

        但是没有任何承诺,它可能会起作用,或者它可能什么都不做。对我来说,正确关闭 Office COM 的东西一直有点像巫术。

        【讨论】:

          【解决方案7】:

          看起来您正在使 Power Point 应用程序实例可见,但如果不可见,则可能存在一个您看不到的对话框 - 可能是一个保存更改对话框。如果应用程序处于隐藏状态,请使其可见,以查看是否弹出任何此类对话框,防止 Power Point 关闭。

          【讨论】:

          • 不,没有这样的东西 :(
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-17
          • 1970-01-01
          • 2018-09-17
          • 1970-01-01
          相关资源
          最近更新 更多