通过C#启动的PowerPoint不会退出

时间:2009-06-11 14:47:37

标签: c# com powerpoint

嘿,我正在使用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();
}

7 个答案:

答案 0 :(得分:12)

首先关闭你的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#

希望这有帮助,让我们知道它是怎么回事......

- 迈克

答案 1 :(得分:2)

以下是一篇描述问题和解决方案的MSDN文章

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

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

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

答案 2 :(得分:2)

Hie folks.lately我发现从垃圾收集到退出和关闭物体没有任何效果。所以我提出了另一种选择。我的工作完成后,我发现了正在运行的进程,然后通过代码将其杀死。

<强>代码:

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

答案 3 :(得分:1)

看起来您正在使Power Point应用程序实例可见,但如果没有,则可能会出现一个您看不到的对话框 - 可能是保存更改对话框。如果应用程序正在隐藏运行,请将其显示为是否弹出任何此类对话框,从而阻止Power Point关闭。

答案 4 :(得分:0)

ppApp 对象调用 Quit()后,请尝试以下

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

然而,没有承诺,它可能会起作用,或者它根本不会做任何事情。正确关闭Office COM的东西对我来说一直有点像伏都教。

答案 5 :(得分:0)

这项工作对我来说

       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();

答案 6 :(得分:0)

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

PP 有时会死机,有时它会在几秒钟内引发很多“ThreadException”直到退出(我猜它真的中止了它的线程)。我已经测试了上述所有代码以及在 Google 中找到的许多其他提示,但均未成功。

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

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

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

SendKeys.Send("%{F4}")

这就是大家...