none
Bug in PowerPoint: intercepting application-level event causes a presentation closed by code to remain in the Presentions collection RRS feed

  • Question

  • Hello,

    Consider a PowerPoint add-in (VSTO) showing two Ribbon buttons calling the following methods when clicked:

    private void button1_Click(object sender, RibbonControlEventArgs e)
    {
        PowerPoint.Presentations presentations = ThisAddIn.instance.Application.Presentations;
        System.Diagnostics.Debug.WriteLine("!!! 1. " + presentations.Count.ToString());
        PowerPoint.Presentation presentation = presentations.Open(@"%file name of existing presentation here%");
        System.Diagnostics.Debug.WriteLine("!!! 2. " + presentations.Count.ToString());
        presentation.Close();
        System.Diagnostics.Debug.WriteLine("!!! 3. " + presentations.Count.ToString());
        Marshal.ReleaseComObject(presentation);
        System.Diagnostics.Debug.WriteLine("!!! 4. " + presentations.Count.ToString());
        Marshal.ReleaseComObject(presentations);
        button2_Click(null, null); 
    }
    
    private void button2_Click(object sender, RibbonControlEventArgs e)
    {
        PowerPoint.Presentations presentations = ThisAddIn.instance.Application.Presentations;
        System.Diagnostics.Debug.WriteLine("!!! button2_Click. " + presentations.Count.ToString());
        for (int i = 1; i <= presentations.Count; i++)
        {
            PowerPoint.Presentation presentation = presentations[presentations.Count];
            System.Diagnostics.Debug.WriteLine("!!! " + i.ToString() + ". " + presentation.FullName);
            Marshal.ReleaseComObject(presentation);
        }
        Marshal.ReleaseComObject(presentations);
        System.Diagnostics.Debug.WriteLine("!!! button2_Click. end");
    }

    That is, when the first button is clicked, you open a presentation and close it. Then you scan the Presentations collection. For the above code to work, modify ThisAddIn_Startup as follows:

    public static ThisAddIn instance;
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        instance = this;
    }

    Starting PowerPoint with the default presentation and clicking the first button produces the following output for me:

    !!! 1. 1 
    !!! 2. 1 
    !!! 3. 0 
    !!! 4. 0 
    !!! button2_Click. 0 
    !!! button2_Click. end 
    

    This is expected: you start with the default presentation (Count=1), opening a presentation closes the default one (Count=1), closing the presentation removes it from the Presentation collection (Count=0).

    Now modify ThisAddIn_Startup as follows:

    public static ThisAddIn instance;
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        instance = this;
        this.Application.WindowSelectionChange += Application_WindowSelectionChange;            
    }
    
    private void Application_WindowSelectionChange(PowerPoint.Selection Sel)
    {
        Marshal.ReleaseComObject(Sel);
    }

    That is, you connect to the WindowSelectionChange event and handle it; the event handler releases the COM object passed.

    Start PowerPoint with the default presentation and click the first button. The code modification above produces the following output for me:

    !!! 1. 1 
    !!! 2. 1 
    !!! 3. 1 
    !!! 4. 1 
    !!! button2_Click. 1 
    !!! 1. %file name of existing presentation here% 
    !!! button2_Click. end 
    
    That is, connecting to an application-level event leaves the presentation closed via Presentation.Close in the Presentations collection. In addition, the code above leaves POWERPNT.EXE hanging in processes. I reproduce the issue in PP 2013 and 2016 32 bit, ClickToRun, all updates installed.

    Actually, it looks like you can use any application-level event instead of WindowSelectionChange. Say, I reproduce the issue by intercepting AfterNewPresentation.

    FYI, the issue was originally found in a COM add-in.


    Regards from Belarus (GMT + 3),

    Andrei Smolin
    Add-in Express Team Leader

    Please mark answers and useful posts to help other developers use the forums efficiently.

    Tuesday, July 5, 2016 2:22 PM

Answers

  • Hi Andrei,

    I assume your issue is caused by that the instance has a reference to WindowSelectionChange, and it failed to release. I suggest you try the code below to remove WindowSelectionChange after you close the presentation.

                PowerPoint.Presentations presentations = ThisAddIn.instance.Application.Presentations;
                System.Diagnostics.Debug.WriteLine("!!! 1. " + presentations.Count.ToString());
                PowerPoint.Presentation presentation = presentations.Open(@"C:\Users\xxx\Desktop\Test.pptx");
                System.Diagnostics.Debug.WriteLine("!!! 2. " + presentations.Count.ToString());
                presentation.Close();
                ThisAddIn.instance.Application.WindowSelectionChange -=Globals.ThisAddIn.Application_WindowSelectionChange;
                System.Diagnostics.Debug.WriteLine("!!! 3. " + presentations.Count.ToString());
                Marshal.ReleaseComObject(presentation);
                System.Diagnostics.Debug.WriteLine("!!! 4. " + presentations.Count.ToString());
                Marshal.ReleaseComObject(presentations);
                button2_Click(null, null);

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    • Marked as answer by Andrei Smolin Thursday, July 7, 2016 12:42 PM
    Thursday, July 7, 2016 6:53 AM

All replies

  • Hi Andrei,

    >> Starting PowerPoint with the default presentation and clicking the first button produces the following output for me

    What do you mean with the default presentation? I made a test with your code under PPT 2016, it output the same result no matter I add WindowSelectionChange or not. What is your issue? Do you mean you close presentation in Button1, and the presentations.Count should be 0 in Button2, but it output the wrong value if you add WindowSelectionChange? Am I right?

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Wednesday, July 6, 2016 6:17 AM
  • Hello Edward,

    Thank you for looking into this.

    The default presentation is the presentation which is opened if you start PowerPoint with the StartUp screen turned off. If the StartUp sreen is shown, you should choose the Blank Presentation on it.

    Do you mean you close presentation in Button1, and the presentations.Count should be 0 in Button2, but it output the wrong value if you add WindowSelectionChange? Am I right?

    Exactly. For me, the output is wrong if WindowSelectionChange or AfterNewPresentation is intercepted.

    File | Account displays the PowerPoint build as 16.0.6995.2058. All other COM add-ins are turned off. There are no other add-ins.


    Regards from Belarus (GMT + 3),

    Andrei Smolin
    Add-in Express Team Leader

    Please mark answers and useful posts to help other developers use the forums efficiently.

    Wednesday, July 6, 2016 7:58 AM
  • Hi Andrei,

    I assume your issue is caused by that the instance has a reference to WindowSelectionChange, and it failed to release. I suggest you try the code below to remove WindowSelectionChange after you close the presentation.

                PowerPoint.Presentations presentations = ThisAddIn.instance.Application.Presentations;
                System.Diagnostics.Debug.WriteLine("!!! 1. " + presentations.Count.ToString());
                PowerPoint.Presentation presentation = presentations.Open(@"C:\Users\xxx\Desktop\Test.pptx");
                System.Diagnostics.Debug.WriteLine("!!! 2. " + presentations.Count.ToString());
                presentation.Close();
                ThisAddIn.instance.Application.WindowSelectionChange -=Globals.ThisAddIn.Application_WindowSelectionChange;
                System.Diagnostics.Debug.WriteLine("!!! 3. " + presentations.Count.ToString());
                Marshal.ReleaseComObject(presentation);
                System.Diagnostics.Debug.WriteLine("!!! 4. " + presentations.Count.ToString());
                Marshal.ReleaseComObject(presentations);
                button2_Click(null, null);

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    • Marked as answer by Andrei Smolin Thursday, July 7, 2016 12:42 PM
    Thursday, July 7, 2016 6:53 AM
  • Thank you Edward!

    You are helpful as always. We try incorporate the code based on this workaround into the code of Add-in Express. Still, I'd like that you inform the PowerPoint team; this bug breaks the rules of the PowerPoint object model.


    Regards from Belarus (GMT + 3),

    Andrei Smolin
    Add-in Express Team Leader

    Please mark answers and useful posts to help other developers use the forums efficiently.

    Thursday, July 7, 2016 12:42 PM