C #: O PowerPoint não parar de fumar?
-
06-07-2019 - |
Pergunta
Eu tenho um script que abre Powerpoint do meu aplicativo e exporta todos os slides. Depois disso, eu preciso que o aplicativo seja fechado.
Eu tentei sem qualquer sorte. Você poderia por favor me ajude?
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);
}
}
}
Solução
Veja a discussão sobre o mesmo tema aqui: c # e automação excel - terminando a instância em execução
Ele cobre Excel, mas os princípios são exatamente o mesmo.
Resumo: você precisa "release" do Presentations
, Slides
e (múltiplos) objetos Slide
. BTW, eu não me incomodaria definindo as variáveis ??como nulo. Isso não é necessário ou útil.
Outras dicas
Se alguém está lutando com isso (não ser capaz de fechar o PPT após iteração através dos slides), mesmo depois de fazer toda a coleta de lixo e liberando recursos, passei a maior parte de hoje coçar a cabeça com um presente. Minha solução foi, em vez de usar um foreach para percorrer os slides, eu fiz o seguinte:
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);
}**
Este é o meu método releaseCOM:
private static void releaseCOM(object o)
{
try
{
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(o);
}
catch { }
finally
{
o = null;
}
}
Como um complemento para a resposta de Gary: A fim de liberar as coleções, você tem que atribuí-los a variáveis ??temporárias. (I utilizado slides e apresentações como variáveis ??temporárias no exemplo abaixo).
// 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();
}
} } }
Eu tenho o código que abre powerpoint do meu aplicativo vb.net, comanda o show de slides, em seguida, fecha-lo depois. Foi uma verdadeira dor nas nádegas para encontrar toda a com objetos que eu tinha que cair depois. Aqui está o código:
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
Espero que isso ajude alguém para pular o esforço extra que eu tinha para colocar em.