在C#中发布PowerPoint Interop Com类成员实例

时间:2016-10-21 15:09:34

标签: c# com powerpoint office-interop dispose

我为Power point创建了一个简单的addIn,这是代码

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

如果 ppApplication 是全局的,则电源点永远不会关闭。我认为全球com对象不会以这种方式释放。我该怎么办?

2 个答案:

答案 0 :(得分:1)

您应该应用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);
        }
    }
}

答案 1 :(得分:1)

遵循此帖Proper way of releasing COM objects?

中的建议
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实例化和发布中是非对称的 - 您在类初始化时实例化(即在变量声明中为a = new()),但在关闭表示时释放。关闭演示文稿与关闭应用程序不同 - 功能区可能仍然可用,这将会咬你。

最后一点是你永远不会解开你已经挂钩到COM对象的事件,你至少应该这样做

ppApplication.PresentationOpen -= new pp.EApplication_PresentationOpenEventHandler(ppApplication_PresentationOpen);
     ppApplication.PresentationClose -= new pp.EApplication_PresentationCloseEventHandler(ppApplication_PresentationClose);

取消分配事件处理程序,否则你有一些不死的引用。