开发者

C#: Powerpoint does not Quit?

I have a script that opens Powerpoint from my application and exports all slides. After that, I need the application to be closed.

I've tried without any luck. Could you please help?

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Powerpoint = Microsoft.Office.Interop.PowerPoint;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
using System.Runtime.InteropServices;

namespace PresentrBuilder
{


class PowerpointConverter
{

    public static void Convert(String file, String safeFile)
    {
        Powerpoint.Application PP;
        Powerpoint.Presentation Presentation;

        PP = new Powerpoint.ApplicationClass();
        PP.Visible = MsoTriState.msoTrue;
        PP.WindowState = Microsoft.Office.Interop.PowerPoint.PpWindowState.ppWindowMinimized;
        Presentation = PP.Presentations.Open(file, MsoTriState.msoFalse, MsoTriState.msoTrue, MsoTriState.msoTrue);

            // Voor elke slide, exporteren
            String exportSlidesPath = Path.Combine(Properties.Settings.Default.CacheDir, @"presentatienaam1\slides");

            // Kijk of de directory bestaat
            if (!Directory.Exists(exportSlidesPath))
            {
                Directory.CreateDirectory(exportSlidesPath);
            }

                // Kijk of er al bestanden in de directory staan
                // Zo ja: verwijderen
                String[] files = Directory.GetFiles(exportSlidesPath, "*.png");
                if (files.Length > 0)
                {
                    foreach (string fileName in files)
                    {
                        File.Delete(Path.Combine(exportSlidesPath, fileName));
                    }
                }

            // Elke slide exporteren
            foreach (Slide slide in Presentation.Slides)
            {
                slide.Export(Path.Combine(exportSlidesPath, "slide_" + slide.SlideIndex + ".png"), "PNG", 1024, 768);
                Marshal.ReleaseComObject(slide);
            }


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

        Marshal.ReleaseComObject开发者_JS百科(PP.Presentations);
        Marshal.ReleaseComObject(Presentation.Slides);

        Presentation.Close();
        Marshal.FinalReleaseComObject(Presentation);

        PP.Quit();
        Marshal.FinalReleaseComObject(PP);

    }

}
}


If anyone else is struggling with this (not being able to close the PPT after iterating through the slides), even after doing all the garbage collection and releasing resources, I spent the better part of today scratching my head with this one. My solution was, instead of using a foreach to iterate through the slides, i did as follows:

        Microsoft.Office.Interop.PowerPoint.Application powerpoint;
        Microsoft.Office.Interop.PowerPoint.Presentation presentation;
        Microsoft.Office.Interop.PowerPoint.Presentations presentations;

        powerpoint = new Microsoft.Office.Interop.PowerPoint.ApplicationClass();
        powerpoint.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
        presentations = powerpoint.Presentations;

        presentation = presentations.Open(localPath, MsoTriState.msoFalse, MsoTriState.msoTrue, MsoTriState.msoTrue);


        //String presentationTitle = objPres.Name;
        Microsoft.Office.Interop.PowerPoint.Slides slides = presentation.Slides;
        **for (int i = 1; i <= slides.Count; i++)
        {
            Microsoft.Office.Interop.PowerPoint.Slide slide = slides[i];
            String slideName = slide.Name;
            releaseCOM(slide);
        }**

This is my releaseCOM method:

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


See the discussion on the same topic here: c# and excel automation - ending the running instance

It covers Excel, but the principles are exactly the same.

Summary: you need to "release" the Presentations, Slides and (multiple) Slide objects. BTW, I wouldn't bother setting the variables to null. That's not necessary or helpful.


As an addition to Gary's answer: In Order to release the collections, you have to assign them to temporary variables. (I used slides and presentations as temp variables in the example below).

  // removed using statements...

    namespace PresentrBuilder
    {


      class PowerpointConverter
      {

      public static void Convert(String file, String safeFile)
      {
        Powerpoint.Application PP;
        Powerpoint.Presentation Presentation;

        PP = new Powerpoint.ApplicationClass();
        // ...
        var presentations = PP.Presentations;
           try
            {
        Presentation = presentations.Open(file, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);

            // Voor elke slide, exporteren
            // ...

            // Elke slide exporteren
            var slides = Presentation.Slides;

            foreach (Slide slide in slides)
            {
                slide.Export(Path.Combine(exportSlidesPath, "slide_" + slide.SlideIndex + ".png"), "PNG", 1024, 768);
                Marshal.ReleaseComObject(slide);
            }
  Marshal.ReleaseComObject(presentations);
        Marshal.ReleaseComObject(slides);

        Presentation.Close();
        Marshal.FinalReleaseComObject(Presentation);
         }
        catch (System.Exception err){}
        finally{

       // GC.WaitForPendingFinalizers();    

        PP.Quit();
        Marshal.FinalReleaseComObject(PP);
        GC.Collect();
      } 
 } } }


I have code that opens powerpoint from my vb.net application, runs the slide show, then closes it afterwards. It was a real pain in the buttocks to find all the com objects I had to drop afterwards. Here's the code:

Imports MSWord = Microsoft.Office.Interop.Word
Imports MSPowerPt = Microsoft.Office.Interop.PowerPoint
Imports MSExcel = Microsoft.Office.Interop.Excel

Dim MSPowerPtApp As MSPowerPt.Application
Dim MSPowerPtPresentation As MSPowerPt.Presentation
Dim MSPowerPtPresentations As MSPowerPt.Presentations
Dim MSPowerPtSettings As MSPowerPt.SlideShowSettings
Dim MSPowerPtSlideShowWindow As MSPowerPt.SlideShowWindow
Dim MSPowerPtSlideShowWindows As MSPowerPt.SlideShowWindows

Function Display_PowerPoint_Show(ByVal filename As String)
  Dim MSPowerPtSlides As MSPowerPt.Slides
  Display_PowerPoint_Show = True
  Try
    If (Not FileExists(filename)) Then
      Display_PowerPoint_Show = False
      MsgBox("Display_PowerPoint_Show: Text file: " & filename & " not found", MsgBoxStyle.Information, "File Not Found")
      GoTo Exit_Display_PowerPoint_Show
    End If

    MSPowerPtApp = New MSPowerPt.Application
    MSPowerPtApp.Visible = True
    MSPowerPtApp.WindowState = MSPowerPt.PpWindowState.ppWindowMinimized

    'Create a new presentation that is based on the specified template.
    MSPowerPtPresentations = MSPowerPtApp.Presentations
    MSPowerPtPresentation = MSPowerPtPresentations.Open(lbFiles.SelectedValue, True)
    MSPowerPtSlides = MSPowerPtPresentation.Slides

    If (MSPowerPtSlides.Count = 0) Then
      MsgBox("This Powerpoint file has no slides", MsgBoxStyle.Information, "No Slides in File")
      GoTo ClosePowerPointFile
    End If

    MSPowerPtSettings = MSPowerPtPresentation.SlideShowSettings
    MSPowerPtSettings.StartingSlide = 1
    MSPowerPtSettings.EndingSlide = 1

    ''Run the slide show and wait for the slide show to end.
    MSPowerPtSlideShowWindow = MSPowerPtSettings.Run()
    MSPowerPtSlideShowWindows = MSPowerPtApp.SlideShowWindows

    Do While MSPowerPtSlideShowWindows.Count >= 1
      System.Windows.Forms.Application.DoEvents()
    Loop

    'Close the presentation without saving changes and then quit MSPowerPt.
    MSPowerPtPresentation.Saved = True
    MSPowerPtPresentation.Close()

    RemoveComObjRef(MSPowerPtSlideShowWindow)
    RemoveComObjRef(MSPowerPtSlideShowWindows)
    RemoveComObjRef(MSPowerPtSettings)

ClosePowerPointFile:
    RemoveComObjRef(MSPowerPtSlides)
    RemoveComObjRef(MSPowerPtPresentation)
    RemoveComObjRef(MSPowerPtPresentations)

    'Quit MSPowerPt.
    MSPowerPtApp.Quit()
    RemoveComObjRef(MSPowerPtApp)
    GC.Collect()

  Catch ex As Exception
    Display_PowerPoint_Show = False
    MsgBox("Display_PowerPoint_Show - File: " & filename & ", Error: " & ex.Message & " reading file", _
           MsgBoxStyle.Information, "Error Reading File")
  End Try

Exit_Display_PowerPoint_Show:
End Function

'RemoveComObjRef function to remove reference.
Private Sub RemoveComObjRef(ByVal ComObject As Object)
  Try
    System.Runtime.InteropServices.Marshal.ReleaseComObject(ComObject)
  Catch
  Finally
    ComObject = Nothing
  End Try
End Sub

I hope this helps someone to skip the extra effort I had to put in.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜