PowerPoint Launched via C# does not Quit

2019-02-12 16:40发布

Hey I'm automating PowerPoint and Excel from a C# WinForms application; what I do is read slides from PowerPoint and save them in Excel and then quit both apps. Excel quits successfully but PowerPoints doesn't quits. The problem is when I convert first time it doesnt quits, but when I convert again it does.

Here is my code

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

6条回答
干净又极端
2楼-- · 2019-02-12 17:16

Shutting down your Microsoft Office application can seem tricky to get right at first, but once you establish the correct order of operations, it's actually not very hard at all.

Releasing your MS Office application can be done safely and effectively in two stages:

(1) First release all the minor objects to which you do not hold a reference within a named variable. You do this via a call to GC.Collect() and then GC.WaitForPendingFinalizers() . Note that if you are using Visual Studio Tools for Office (VSTO), then you need to call this pair of commands twice in order to get the COM objects to successfully release. You are not using VSTO, however, so calling them once is sufficient.

(2) Then explicitly release the objects which you hold via a named variable using a call to Marshall.FinalReleaseComObject() on each variable you have.

Remember to explicitly release all variables that you have to COM components. If you miss even one, then your MS Office application will hang. In your code, you seem to have three named variables that hold a reference to your PowerPoint application: ppApp, ppPres, and cell.

Taking this all into account, I think that your cleanup should look something like the following, which makes use of using System.Runtime.InteropServices either within the namespace or at the top of the code document:

// using System.Runtime.InteropServices

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

Marshal.ReleaseComObject(cell);

ppPres.Close();
Marshal.ReleaseComObject(ppPres);

ppApp.Quit();
Marshal.ReleaseComObject(ppApp);

Give it a try, I think this should work for you... (If not, you might have to show even more of your code.) For further information, I give a detailed explanation on how to properly release an Excel application here:

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

Hope this helps, let us know how it goes...

-- Mike

查看更多
Evening l夕情丶
3楼-- · 2019-02-12 17:16

Here is a MSDN article that describes the problem and solution

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

basically recomondation is to do(Note : two iterations of GC.Collect()

 GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.WaitForPendingFinalizers(); 
查看更多
欢心
4楼-- · 2019-02-12 17:21

This Work for me

       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();
查看更多
Evening l夕情丶
5楼-- · 2019-02-12 17:23

Hie folks.lately i have observed that nothing worked out for me from garbage collect to quitting and closing objects. so i came up with an alternative. i found out the running process once my job was done,and then killed it through code.

Code:

 Process[] pros = Process.GetProcesses();
  for (int i = 0; i < pros.Count(); i++)
   {
   if (pros[i].ProcessName.ToLower().Contains("powerpnt"))
        {
          pros[i].Kill();
        }
   }
查看更多
做个烂人
6楼-- · 2019-02-12 17:36

It looks like you are making the Power Point application instance visible, but if not, it's possible that there is a dialog being presented that you don't see - perhaps a save changes dialog. If the app is running hidden, make it visible to see if any such dialogs are popping up, preventing Power Point from closing.

查看更多
老娘就宠你
7楼-- · 2019-02-12 17:39

After invoking Quit() for your ppApp object try the following

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

No promises however, it might work, or it might do nothing at all. Properly closing down Office COM stuff has always been a bit like voodoo for me.

查看更多
登录 后发表回答