C #: Powerpoint nicht beenden?
-
06-07-2019 - |
Frage
Ich habe ein Skript, das Powerpoint aus meiner Anwendung öffnet und exportiert alle Folien. Danach muss ich die Anwendung geschlossen werden.
Ich habe ohne Erfolg versucht. Könnten Sie bitte helfen?
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);
}
}
}
Lösung
Siehe auch die Diskussion zum gleichen Thema hier: c # und Excel-Automatisierung - die Beendigung der laufenden Instanz
Es umfasst Excel, aber die Prinzipien sind genau gleich.
Zusammenfassung: Sie müssen "Freigabe" die Presentations
, Slides
und (Mehrfach-) Slide
Objekte. BTW, würde ich nicht die Mühe, die Variablen auf null zu setzen. Das ist nicht nötig oder hilfreich ist.
Andere Tipps
Wenn jemand andere mit dieser kämpft (nicht in der Lage ist, um die PPT nach Iterieren durch die Folien zu schließen), auch nach all der Garbage-Collection zu tun und Ressourcen freigegeben wird, verbrachte ich den größten Teil des heutigen Tages mit diesem Kopf kratzen. Meine Lösung war, anstatt eine foreach der Verwendung durch die Folien zu durchlaufen, ich habe wie folgt:
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);
}**
Das ist meine releaseCOM Methode:
private static void releaseCOM(object o)
{
try
{
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(o);
}
catch { }
finally
{
o = null;
}
}
Als Ergänzung zu Gary Antwort: Um die Sammlung zu veröffentlichen, müssen Sie diese temporären Variablen zuzuweisen. (I verwenden Folien und Präsentationen als temporäre Variablen im Beispiel unten).
// 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();
}
} } }
Ich habe Code, den Powerpoint aus meiner vb.net Anwendung öffnet, wird die Diashow, dann schließt es danach. Es war ein echten Schmerzen im Gesäß all COM-Objekte zu finden, wie ich später fallen zu lassen hatte. Hier ist der 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
Ich hoffe, das hilft jemand den zusätzlichen Aufwand überspringen ich in setzen musste.