none
Word Add-in Not Releasing a New Instance of PowerPoint RRS feed

  • Question

  • I have a Word 2007 and 2010 VSTO 2010 add-in. From UI ribbon control a new instance of PowerPoint can be initiated so that slide images can be inserted into the active document. The code I use to initiate the PowerPoint instance is:

            If Process.GetProcessesByName("POWERPNT").Count > 0 Then
                pApp = Marshal.GetActiveObject("PowerPoint.Application")
                pApp.Visible = True
                newPPT = False
            Else
                pApp = New PowerPoint.Application
                pApp.Visible = True
                newPPT = True
                pApp.WindowState = PowerPoint.PpWindowState.ppWindowNormal
            End If
    
    

    If the subroutine initiated the instance of PowerPoint, at then end of the insert slides routine I want to quit PowerPoint. I am using the following code for that purpose:

            If newPPT = True Then
                ppt.Save()
                ppt.Close()
                If Not pApp Is Nothing Then
                    pApp.Quit()
                    pApp = Nothing
                    GC.Collect()
                    GC.WaitForPendingFinalizers()
                    GC.Collect()
                    GC.WaitForPendingFinalizers()
                End If
            End If
    
    

    The problem I am having is that PowerPoint will not release.  The only way to "sometimes" make it release is to close the active document.  Programmatically however, this is not a consistent behavior and it appears to be related to code execution timing.  You can see that I've attempted to use the Garbage Collector routine but it is having no effect.  The instance of PowerPoint will consistently release if the user closes the active document.
    Any advice or recommendation for solution is much appreciated.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Tuesday, September 27, 2011 7:36 PM

Answers

  • Hi Rich,

    I'm not sure if you have read this KB article:

    http://support.microsoft.com/kb/317109

    You can have a try to release COM resources by using the following code:

    private void NAR(object o)
    {
        try 
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
        }
        catch {}
        finally 
        {
            o = null;
        }
    }
    

    I look forward to hearing of you.


    Best Regards, Calvin Gao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, September 28, 2011 10:25 AM
    Moderator
  • Hi Rich,

    Don't use foreach loops, use for loops instead.

    Don't call PowerPointApp.Presentations.Item(i), use this template instead (a raw sketch): 

    dim presentations as PowerPoint.Presentations = PowerPointApp.Presentations
    
    dim presentation as PowerPoint.Presentation = presentations .Item(i)
    
    ' your stuff
    
    If presentation IsNot Nothing Then Marshal.ReleaseComObjects(presentation)
    
    If presentations IsNot Nothing Then Marshal.ReleaseComObjects(presentations)
    
    

    You'll find other useful suggestions in When to release COM objects in Office add-ins developed in .NET.


    Regards from Belarus (GMT + 2),

    Andrei Smolin
    Add-in Express Team Leader
    Wednesday, September 28, 2011 12:56 PM

All replies

  • Hello Rich,

    Turn off every COM add-in in PP. Check if the issue is produced by VBA code in the presentation or template.

    Then try to isolate the issue by commenting out your code accessing the PowerPoint object model and then uncommenting it block by block. 

    Pay attention to releasing COM collections (such as Presentations) as well as objects having "Active" in the corresponding property name.


    Regards from Belarus (GMT + 2),

    Andrei Smolin
    Add-in Express Team Leader
    • Edited by Andrei Smolin Wednesday, September 28, 2011 7:40 AM correction
    Tuesday, September 27, 2011 9:18 PM
  • Hi Rich

    If release is consistent when the user closes the ActiveDocument then it might help us to know exactly what kinds of things your code is doing that might "link" the two apps. Are you using Copy/Paste, for example?


    Cindy Meister, VSTO/Word MVP
    Wednesday, September 28, 2011 9:27 AM
    Moderator
  • Hi Cindy,

    A nice shot!

    > Are you using Copy/Paste, for example?

    ... or drag-n-drop?


    Regards from Belarus (GMT + 2),

    Andrei Smolin
    Add-in Express Team Leader
    Wednesday, September 28, 2011 9:44 AM
  • Hi Rich,

    I'm not sure if you have read this KB article:

    http://support.microsoft.com/kb/317109

    You can have a try to release COM resources by using the following code:

    private void NAR(object o)
    {
        try 
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(o);
        }
        catch {}
        finally 
        {
            o = null;
        }
    }
    

    I look forward to hearing of you.


    Best Regards, Calvin Gao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, September 28, 2011 10:25 AM
    Moderator
  • Hi Cindy,

    Yes I use a Copy/Paste to pickup the slide image and optionally the notes area of the slide. Is there another way? If there is ... you've made my day!:-)


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 12:02 PM
  • Thanks Calvin ...

    No I hadn't seen this article but I had tried the RealseComObject command but with no joy. However, after reading this article I'm wondering if the problem is that I'm not separating out "Presentations" as a unique object. I set an object for the PowerPoint application and also one for a single presentation, but not one for all presentations. 

    I wonder if that's the issue ... I'll run some test today.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 12:08 PM
  • Hi Andrei,

    There's no other comm objects or VBA code and I've been trying to isolate each part of the the code and moving things around it see it's impact.  The releasing of COM collections is something I need to look more closely at ... thanks for pointing that out.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 12:11 PM
  • Hi Cindy,

    I might have finally figured out why you asked about Copy/Paste and the two applications remaining linked. I paste into the Word document using this command.

    If Forms.Clipboard.ContainsImage Then
         scrRng.PasteSpecial(Placement:=Word.WdOLEPlacement.wdInLine, DataType:=Word.WdPasteDataType.wdPasteMetafilePicture)
    End If

    And then use a scrRng.Fields.Unlink command to make sure it's uncoupled from PowerPoint. 


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 12:51 PM
  • Hi Rich,

    Don't use foreach loops, use for loops instead.

    Don't call PowerPointApp.Presentations.Item(i), use this template instead (a raw sketch): 

    dim presentations as PowerPoint.Presentations = PowerPointApp.Presentations
    
    dim presentation as PowerPoint.Presentation = presentations .Item(i)
    
    ' your stuff
    
    If presentation IsNot Nothing Then Marshal.ReleaseComObjects(presentation)
    
    If presentations IsNot Nothing Then Marshal.ReleaseComObjects(presentations)
    
    

    You'll find other useful suggestions in When to release COM objects in Office add-ins developed in .NET.


    Regards from Belarus (GMT + 2),

    Andrei Smolin
    Add-in Express Team Leader
    Wednesday, September 28, 2011 12:56 PM
  • Hi Rich

    Well, I asked because with Office, if you put a large amount of information on the Clipboard, it can "tie things down". Excel always maintains a link to the Clipboard - if that gets broken, there's no content.

    With Word, if you want to quit, you'll get a message like (but not verbatim), "you put a large amount of data on the Clipboard. Do you want to keep it for use after you quit word?"

    If Word's showing this message, then it won't quit. I'm just wondering if PowerPoint does something similar?

    With Word, if that can be a problem, you copy like a single space in order to kick out that large amount of data...


    Cindy Meister, VSTO/Word MVP
    Wednesday, September 28, 2011 12:59 PM
    Moderator
  • Hi Cindy,

    I don't get that Word message in this case because after the paste I'm resetting the clipboard image to nothing.

    I know, at least in prior Word versions, if you did not "Unlink" the pasted slide, that a link to PowerPoint was maintained on each image ... a lot of overhead and I'd guess that this would prevent the release of PowerPoint.  Since I am unlinking, I don't believe that to be the problem in this case.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 1:44 PM
  • Hi Rich

    If, as you say, you're "because after the paste I'm resetting the clipboard image to nothing." then the scenario I had in mind is probably not the case. (Although the message would be appearing in POWERPOINT, not Word.)

    But do you have the PowerPoint window visible? If you try to quit PPT as an end-user, instead of asking your code to do it do you get any prompts?


    Cindy Meister, VSTO/Word MVP
    Wednesday, September 28, 2011 1:52 PM
    Moderator
  • Hi Cindy,

    Yes when the routine ends an empty PowerPoint windows is visible and closing it manually does not produce a message, nor does it release the instance of PowerPoint running. (Checked via Task Manager)

    I have also verified after each Copy/Paste/Clipboard Image Reset that that clipboard is indeed empty and it is empty just prior to the the code's attempt to quit PowerPoint.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 2:03 PM
  • Hi Rich

    OK, would have been nice...

    So...

    1. You could theoretically use the Open XML file format to extract the information from the closed PPT files and insert it into Word (you'd just have to see how to "convert" from the PPT Open XML to the Word Open XML)

    2. You could save the PPT object (slide?) to a graphics file and insert into Word? (Which would probably have a lot less overhead, in any case).

    And that brings to mind: when you paste in Word, what exactly are you pasting? A PowerPoint slide object? Do you need an OLE object or would it do just as well to Paste Special in some graphics format?

    I can't help but thinking this has something to do with Word holding an OLE connection to the PowerPoint application.


    Cindy Meister, VSTO/Word MVP
    Wednesday, September 28, 2011 2:12 PM
    Moderator
  • Hi Cindy,

    Concerning OpenXML ... I suppose that would work if I knew more about OpenXML. It's sad to say that I'm ignornant on that method and it's on my "to learn how" list but not for today. :-)

    Concerning saving the PPT object as a file ... I tried that but unfornately it does not provide a file with sufficent quality resolution (when printed). Even the EMF or WMF formats are of low quality. What "I think I have learned" about pulling the images out of PowerPoint is the only method, which results in a high quality image, is to first paste it into a document using the data type of: DataType:=Word.WdPasteDataType.wdPasteMetafilePicture 

    Doing this results in an assembled image in the documents xml media folder of a high quality WMF image file and as I said earlier, creating a WMF image directly from the PPT object does not produce the same quality WMF image file.  Thus I conclude that Word is doing more to enhance the image that it is saving into the document than PowerPoint does when it saves the assembled slide object as an image. There is obviously more here on this point that I need to try and figure out and see if I can make it work.

    I have used the term "assembled" a couple of times to describe the slide object because one other thing I again "think I have learned" is that PowerPoint does not keep a Slide as an assembled image, it keeps the parts and this is true at least for pptx files. The slide is actually more like a layered PhotoShop file and this onto itself also causes problems with Copy/Pastes as well as Convert to Image, which I have yet to make another Forum Post about.  But I digress ...

    Regarding the OLE object reference ... I agree with you. However, if you don't use that property on the Paste Special the image is inserted in a different aspect ratio, more like a letter box elongated size and this distorts all of the shapes on the slide.

    BTW I do plan on chatting with the folks on the PowerPoint Answers forum as well but first I want to see if I can resolve this release issue with the help you, Andrei, and Calvin have given me.

    Thanks again! :-)


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 2:54 PM
  • Hi Andrei,

    A follow-up question. Your recommendation of not using For Each loops and instead to use For loops ... is this regarding the ability to later release the objects or is it for speed or some other purpose?

    Thanks


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 3:40 PM
  • This is about releasing COM objects. As far as I understand foreach creates an enumerator which creates and doesn't release COM objects.
    Regards from Belarus (GMT + 2),

    Andrei Smolin
    Add-in Express Team Leader
    Wednesday, September 28, 2011 3:51 PM
  • This is about releasing COM objects. As far as I understand foreach creates an enumerator which creates and doesn't release COM objects.


    Regards from Belarus (GMT + 2),

    Andrei Smolin
    Add-in Express Team Leader
    Wednesday, September 28, 2011 3:55 PM
  • Hi Rich

    <<Regarding the OLE object reference ... I agree with you. However, if you don't use that property on the Paste Special the image is inserted in a different aspect ratio, more like a letter box elongated size and this distorts all of the shapes on the slide.>>

    Got it :-)

    Andrei might be on to something with the For Each. That aspect of using it never occurred to me before, but it appears today is a day to learn all kinds of things (PhoneticGuide method was an eye-opener).

    An alternate way to go about it might be to first paste these things into another "scratch" document and take them from there (Range.FormattedText?) into the "real" document. When you're done, throw away the scratch document which will, we can hope, release PPT?


    Cindy Meister, VSTO/Word MVP
    Wednesday, September 28, 2011 4:46 PM
    Moderator
  • With the help of Andrei, Calvin, and Cindy I’ve resolved the issue.  It was rather complex and the clues did come from everyone.

    To say more about my scenario:

    The UI controls calls an ImportSlides code module.  The ImportSlides module is the main body of code and opens a Windows form named frmSlides, which checks an existing instance of PowerPoint and opens a new instance if an existing one is not found.  frmSlides also controls the dialog with the user for setting various parameters about what they want to import into their Word document. Finally complicating things a bit more is that frmSlides optionally can open another Windows form called frmTags if the user needs to place some meta-tags on various slides.

    Once all of the user interaction is complete, control returns to the ImportSlides module that takes care of the actual copy, pasting, formatting, etc. of the slides into the user’s Word document.

    Each of these functions, two Window form classes and one code module, needed to interact with PowerPoint and I think that was part of problem, at least from how I had implemented it.  I had tried to isolate each by using local private variables and I had not isolated an object for PowerPoint.Presentations. I had only object variables for PowerPoint.Application and PowerPoint.Presentation.

    The solution that works:

    1.       Public variables for PowerPoint.Application, Presentations, and Presentation that all routines now reference

    2.       These three variables are declared in the ImportSlides code module

    3.       At the completion of the ImportSlides routine the following code is executed and PowerPoint is successfully released:

     

    By the way, the For each Sld in ppt.Slides command did not cause an issue for me. Maybe due to the fact that it executes in the ImportSlides module … now the only code class/module that actually contains the object references to PowerPoint.

     

            If newPPT = True Then
    
                ppt.Save()
    
                ppt.Close()
    
                If ppt IsNot Nothing Then Marshal.ReleaseComObject(ppt)
    
                If pPres IsNot Nothing Then Marshal.ReleaseComObject(pPres)
                
                pApp.Quit()
    
    
                If pApp IsNot Nothing Then Marshal.ReleaseComObject(pApp)
    
                            ppt = Nothing
    
                pPres = Nothing
    
                pApp = Nothing
    
                GC.Collect()
    
                GC.WaitForPendingFinalizers()
    
                GC.Collect()
    
                GC.WaitForPendingFinalizers()
    
            End If
    
    
    
    


     


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 5:27 PM
  • Rich,

    The code lines below should be put in the reverse order. Otherwise the second line will fire an exception because pApp is released.

                If pApp IsNot Nothing Then Marshal.ReleaseComObject(pApp)
                pApp.Quit()

     

     


    Regards from Belarus (GMT + 2),

    Andrei Smolin
    Add-in Express Team Leader
    Wednesday, September 28, 2011 7:07 PM
  • Hi Andrei,

    That's weird because I got an exception when I had the Release after the Quit.

    I'll test it again.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 7:18 PM
  • Hi Andrei,

    It didn't provide an error either way but I've changed my code to your recommendation.  Thank you!

    I will also try to edit my message above and correct the code so that anyone else reading the thread will see the correct method.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 7:45 PM
  • An alternate way to go about it might be to first paste these things into another "scratch" document and take them from there (Range.FormattedText?) into the "real" document. When you're done, throw away the scratch document which will, we can hope, release PPT?


    Cindy Meister, VSTO/Word MVP

    Hi Cindy,

    Just as a follow-up on this last point you made. I actually do first paste the image into a scratch document and use the range.formattedtext command to move it over to the real document.  It's all about speed really.

    The "real" document is a huge table and working directly in it, really slows down the whole process. I've found it best to work in a throw away and then move the formatted range over when I'm ready.


    Kind Regards, Rich ... http://greatcirclelearning.com
    Wednesday, September 28, 2011 8:52 PM