-1

I create a simple addIn for Power point and this is the code

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 never close if ppApplication is global. I think global com object dose not release in this way. What should I do?

Alex
  • 8,827
  • 3
  • 42
  • 58
a.Fard
  • 21
  • 1
  • 1
    Why are you using `new pp.Application()` in a PowerPoint add-in? You should have a `this.Application` member. Also, C# has no "global" variables, what do you mean by that? – CodeCaster Oct 21 '16 at 15:13
  • Your event handlers on ppApplication may be creating a dependency which prevents ppApplication from being released. Try removing the hooked event handlers when you get to PresentationClosed event. – PhillipH Oct 21 '16 at 15:31

2 Answers2

1

You should apply Dispose/Finalize pattern to free you unmanaged resource properly. This will guarantee that once your class will be disposed, all unmanaged class members (not global variables) would be released. See 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);
        }
    }
}
Alex
  • 8,827
  • 3
  • 42
  • 58
  • @codeCaster I'm actually interested in the comments of the correctness of the example I've provided for proper disposing of interop objects. Maybe somebody could give some comments on this approach as there are a lot of opinions about this. – Alex Oct 21 '16 at 15:41
1

Following the recommendation in this post 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.

You should call

pp.Application ppApplication = new pp.Application();

within Ribbon_Load

Also you are asymmetric in your COM Instantiation and Release - you instantiate on class initialize (i.e. as a = new() in the variable declaration) but release when the presentation is closed. Closing a presentation isn't the same as closing the application - the ribbon is probably still available, and this will come to bite you.

The last point is that you never unhook the events you've hooked into the COM object, you should at least be doing

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

to deallocate the event handlers, otherwise you have some undead references.

Community
  • 1
  • 1
PhillipH
  • 6,182
  • 1
  • 15
  • 25