Освободить экземпляр класса PowerPoint Interop Com в C#
Я создаю простой надстройку для Power Point, и это код
pp.Application ppApplication = new pp.Application();
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
ppApplication.PresentationOpen += new pp.EApplication_PresentationOpenEventHandler(ppApplication_PresentationOpen);
ppApplication.PresentationClose += new pp.EApplication_PresentationCloseEventHandler(ppApplication_PresentationClose);
}
void ppApplication_PresentationOpen(pp.Presentation Pres)
{
}
void ppApplication_PresentationClose(pp.Presentation Pres)
{
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(ppApplication);
}
Power point никогда не закрывается, если ppApplication является глобальным. Я думаю, что глобальная ком-объектная доза не выделяется таким образом. Что я должен делать?
2 ответа
Следуя рекомендации в этом посте Правильный способ освобождения COM-объектов?
1) Declare & instantiate COM objects at the last moment possible.
2) ReleaseComObject(obj) for ALL objects, at the soonest moment possible.
3) Always ReleaseComObject in the opposite order of creation.
4) NEVER call GC.Collect() except when required for debugging.
Вам следует позвонить
pp.Application ppApplication = new pp.Application();
в пределах Ribbon_Load
Кроме того, вы асимметричны в своем COM Instantiation and Release - вы создаете экземпляр класса initialize (то есть как a = new() в объявлении переменной), но освобождаетесь, когда презентация закрыта. Закрытие презентации - это не то же самое, что закрытие приложения - лента, вероятно, все еще доступна, и это вас укусит.
Последнее, что вы никогда не отцепляете события, которые вы подключили к COM-объекту, вы должны, по крайней мере, делать
ppApplication.PresentationOpen -= new pp.EApplication_PresentationOpenEventHandler(ppApplication_PresentationOpen);
ppApplication.PresentationClose -= new pp.EApplication_PresentationCloseEventHandler(ppApplication_PresentationClose);
чтобы освободить обработчики событий, в противном случае у вас есть несколько ссылок нежити.
Вам следует применить шаблон Dispose/Finalize, чтобы правильно освободить неуправляемый ресурс. Это гарантирует, что после удаления вашего класса будут освобождены все неуправляемые члены класса (не глобальные переменные). См. https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx
using System;
using System.Runtime.InteropServices;
namespace PowerPointTestApp
{
class Program
{
static void Main(string[] args)
{
using (Container c = new Container())
{
Console.WriteLine("Opened..");
}
Console.WriteLine("Closed..");
}
}
public class Container: IDisposable
{
Microsoft.Office.Interop.PowerPoint.Application pp = new Microsoft.Office.Interop.PowerPoint.Application();
public Container()
{
pp.PresentationOpen += (pres)=>
{
//DoSomething
};
pp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
pp.Quit();
Marshal.FinalReleaseComObject(pp);
}
}
~Container()
{
Dispose(false);
}
}
}