【问题标题】:C#: Powerpoint does not Quit?C#:Powerpoint 不退出?
【发布时间】:2014-06-26 03:05:39
【问题描述】:

我有一个脚本可以从我的应用程序中打开 Powerpoint 并导出所有幻灯片。 之后,我需要关闭应用程序。

我试过没有任何运气。你能帮忙吗?

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(PP.Presentations);
        Marshal.ReleaseComObject(Presentation.Slides);

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

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

    }

}
}

【问题讨论】:

  • 您已经编辑了上面的代码,但仍然不正确。您调用 PP.Presentations(和 Presentation.Slides)两次,一次使用它们,然后一次释放引用。但是它不是这样工作的——每次调用它们时,都会创建另一个引用。您需要调用它们一次,并将引用存储在一个变量中,然后您可以释放(根据安德烈的回答)。
  • 在完成此方法调用后,尝试从另一个方法调用 Collect and Wait

标签: c# visual-studio com powerpoint


【解决方案1】:

如果其他人正在为此苦苦挣扎(遍历幻灯片后无法关闭 PPT),即使在完成所有垃圾收集和释放资源之后,我今天大部分时间都在为这个挠头。我的解决方案是,我没有使用 foreach 遍历幻灯片,而是执行以下操作:

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

这是我的 releaseCOM 方法:

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

【讨论】:

    【解决方案2】:

    在此处查看关于同一主题的讨论:c# and excel automation - ending the running instance

    它涵盖了Excel,但原理完全相同。

    总结:您需要“释放”PresentationsSlides 和(多个)Slide 对象。顺便说一句,我不会费心将变量设置为空。这没有必要也没有帮助。

    【讨论】:

    • 嗯,我已经尝试释放所有引用 Powerpoint 的对象,但似乎没有任何帮助...我正在使用 Marshal.ReleaseComObject(slide); 释放所有 Slide 对象; .
    • 您是否也发布了 PP.Presentations 和 Presentation.Slides 对象?人们经常忘记使用的集合。
    • 能否请您编辑您的问题并发布您更新的代码?
    【解决方案3】:

    作为加里回答的补充: 为了释放集合,您必须将它们分配给临时变量。 (在下面的示例中,我使用幻灯片和演示文稿作为临时变量)。

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

    【讨论】:

    • 我已经用你的例子编辑了我的代码,但也没有运气。我不明白,因为似乎所有与 Powerpoint 的引用都已发布。
    • 只是猜测:您是否尝试在发布 Presentation 和 PP 后调用 GC.Collect?
    【解决方案4】:

    我的代码可以从我的 vb.net 应用程序打开 powerpoint,运行幻灯片,然后关闭它。找到之后我不得不丢下的所有 com 对象真的让我感到非常痛苦。代码如下:

    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
    

    我希望这可以帮助某人跳过我必须付出的额外努力。

    【讨论】:

      猜你喜欢
      • 2010-11-02
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 1970-01-01
      相关资源
      最近更新 更多