none
Correct way to access PowerPoint object model in external application RRS feed

  • Question

  • I'm developing a WPF application that consumes PowerPoint content.  I've been using the PPT Object model to scan through presentations and export the contents in another format.

    The current code accesses the PPT object model using something like this:

     using Microsoft.Office.Core;
     using Powerpoint = Microsoft.Office.Interop.PowerPoint;

     class MyClass
     {

      Powerpoint.Application pptApplication;
      Powerpoint.Presentation pptPresentation;

      void MyInit(string fileName)
      {

                     this.pptApplication = new Microsoft.Office.Interop.PowerPoint.Application();

                     this.pptPresentation = m_appPowerpoint.Presentations.Open(
                         fileName),    // FileName to open
                         MsoTriState.msoTrue,                // Opens the file with read-only status.
                         MsoTriState.msoTrue,                // The file name automatically becomes the title of the opened presentation
                             MsoTriState.msoFalse                // Do not show the opened presentation.
                                );
      }

    But this approach has some problems:

    1) If my application is running and the user attempts to launch PowerPoint -- the PowerPoint application window never appears.

    2) If PowerPoint is already running the PowerPoint Application() constructor throws a ComException after a lengthy delay.

    So I'm wondering what the supported approach is for accessing the PPT object model from an external application, while still allowing the end-user to use PowerPoint.

    Thanks
     

    Saturday, March 12, 2011 7:05 PM

All replies

  • Hi Randy,

    Thanks for posting in the MSDN Forum.

    Do you want to show PowerPoint Slide? You need to set SlideShowSeting Property of  your Presentiation instance. Please try this snippet:

    PowerPoint.Application app = new PowerPoint.Application();
          PowerPoint.Presentation presentation = app.Presentations.Open(@"[You PowerPoint file path]", MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse);
          PowerPoint.SlideShowSettings sst = presentation.SlideShowSettings;
          sst.ShowType = PowerPoint.PpSlideShowType.ppShowTypeWindow;
          sst.Run();
    

    Have a good day,

    Tom


    Tom Xu [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.

    Monday, March 14, 2011 3:15 AM
    Moderator
  • The problem I'm having is that if POWERPNT.EXE is already running on the machine when the application attempts to create a Power Point Application object that the Application contstructor throws an exception after a lengthy delay (several seconds)

    This line:

    this.pptApplication = new Microsoft.Office.Interop.PowerPoint.Application();

    Throws this exception

    An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll

    Additional information: Retrieving the COM class factory for component with CLSID {91493441-5A91-11CF-8700-00AA0060263B} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

    Debug trace from just before the exception:

     'Symphony.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.PowerPoint\14.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.PowerPoint.dll'
    'Symphony.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\assembly\GAC_MSIL\office\14.0.0.0__71e9bce111e9429c\office.dll'
    The thread '<No Name>' (0x3d4c) has exited with code 0 (0x0).
    'Symphony.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Accessibility\v4.0_4.0.0.0__b03f5f7f11d50a3a\Accessibility.dll'
    A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll
    An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll

    Additional information: Retrieving the COM class factory for component with CLSID {91493441-5A91-11CF-8700-00AA0060263B} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

     

    Monday, March 14, 2011 3:48 PM
  • Hi Randy,

    This problem isn’t related to a PowerPoint.exe is already running. I can run my snippet when a PowerPoint already exists on my side.

    And the exception message mean is that perhaps you run many COM+ component services on your side.

    Please take a look at http://support.microsoft.com/kb/870655 . I hope it can help you.

    Have a good day,

    Tom


    Tom Xu [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, March 16, 2011 10:55 AM
    Moderator
  • That's an interesting KB -- but it seems pretty unrelated to the circumstances I'm encountering -- the repro steps listed in the KB use 100 as the number of COM+ applications at one time to generate the error under 100 different local accounts -- I'm not doing anything like that,  just one user account.  I've have just Outlook, Power Point, Visual Studio, IE9 and the application I'm developing running when I encounter the problem.

    I'll have my testers apply the work-around in the lab and see if helps with the issue.

    Wednesday, March 16, 2011 4:34 PM
  • FYI: I have the same problem and I can confirm it is caused by PowerPoint already running. If you ever implemented a work around, please post. I'll work on checking if PowerPoint is running and closing PowerPoint if it is, before my code starts. If you have a better solution, can you share?

    Thanks,

    Bart


    Bart Roozendaal, Sevensteps Microsoft MVP for Surface

    Sunday, January 5, 2014 12:19 PM
  • Hi Bart

    The better place to ask this would probably be in a venue where the Powerpoint specialists (MVPs) hang out, which would be the "Communities" (yes, even the devs congregate there):

    http://answers.microsoft.com/en-us/office/forum/powerpoint

    But FWIW in my experience you can't run a second instance of PowerPoint - only one will run. That may be the reason for the error you're getting. It might be a good idea to first check the Processes to determine whether PowerPoint is already running. Using GetActiveObject you can then "hook into" the running process.

    Depending on what it is you need to do with PowerPoint, and in what kind of environment, perhaps it would be better to work with the closed file using the Open XML SDK? Or have an add-in that's running in-process?


    Cindy Meister, VSTO/Word MVP, my blog

    Sunday, January 5, 2014 2:59 PM
    Moderator
  • He Cindy,

    Thanks for your answer. I've found that GetActiveObject("Powerpoint.Application") doesn't return an object if you just started Powerpoint, not using the Powerpoint Interops. My current implementation (which seems to handle all situations) is found below. Hope it will help others later on.

    Bye,

    Bart

    /// <summary>
    /// Ensure that PowerPoint is running and accessible. It will:
    /// 1) Try to connect to a running PowerPoint.Application
    /// 2) If unsuccessful, check if PowerPoint.exe is running and close that if that is the case
    /// 3) If that worked, start a new PowerPoint.Application
    /// </summary>
    /// <returns>True if successful, or False if not</returns>
    public bool EnsurePowerPoint()
    {
    	// Startup PowerPoint using the Office interop library. We're using version 12 here, since the customer uses Office 2007
    	if (null == _powerpointApp)
    	{
    		// First, check if POWERPNT.EXE is a running application. Can be an unwanted left over or a manually started PowerPoint instance
    		// Could (probably) also be another application using PowerPoint interops, in which case we're stealing their instance. 
    		// Might interfere with that other application, but this control is not intended for side by side use
     
    		//Get reference to Excel.Application from the ROT.
    		try
    		{
    			_powerpointApp = (Microsoft.Office.Interop.PowerPoint.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Powerpoint.Application");
    			if (_powerpointApp != null)
    			{
    				_powerpointApp.WindowState = Microsoft.Office.Interop.PowerPoint.PpWindowState.ppWindowMinimized;
    			}
    		}
    		catch (COMException)
    		{
    			// If no instance was running, this exception is thrown. Should be the case under normal circumstances
    			// Also sometimes (maybe only during development), an exception is thrown, mentioning open dialogs.
    			_powerpointApp = null;
     
    		}
    		catch (Exception ex)
    		{
    			// Something else went wrong
    			Logger.LogException(ex);
    		}
     
    		if (null == _powerpointApp)
    		{
    			// If no PowerPoint instance was running, check for a running process. It could be a manual PowerPoint was started, which we can't connect to
    			try
    			{
    				Process[] powerPointsRunning = Process.GetProcessesByName(cPowerPointTaskName);
    				if (powerPointsRunning.Length > 0) // Yes, it is
    				{
    					foreach (var powerpointRunning in powerPointsRunning)
    					{
    						powerpointRunning.Kill(); // Just kill it
    					}
    					Thread.Sleep(500); // Half a second should do it. Open dialogs and changes are ignored. Tough luck
    				}
    			}
    			catch (Exception ex)
    			{
    				// For good measure, catch exceptions and log them
    				Logger.LogException(ex);
    			}
    			Process[] powerPointsRunning2 = Process.GetProcessesByName(cPowerPointTaskName);
    			if (powerPointsRunning2.Length > 0)
    			{
    				// We were unsuccessful in closing PowerPoint. Report and return false
    				Logger.LogWarning(@"Unable to close down running instance of PowerPoint.");
    				return false;
    			}
     
    			// Now, launch a new instance
    			try
    			{
    				_powerpointApp = new Microsoft.Office.Interop.PowerPoint.Application();
    				if (_powerpointApp != null)
    				{
    					// This will make sure the PowerPoint windows are fully created. It causes some flickering, but we can't do much about that. We need the Windows created before we start the slideshow
    					_powerpointApp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
    					_powerpointApp.WindowState = Microsoft.Office.Interop.PowerPoint.PpWindowState.ppWindowMinimized;
    				}
    			}
    			catch (COMException ex)
    			{
    				Logger.LogException(ex);
    			}
    		}
     
    		if (null == _powerpointApp)
    		{
    			// We couldn't start. Maybe PowerPoint isn't installed?
    			Logger.LogWarning(@"Could not launch PowerPoint 2007. Is it installed?");
    			return false;
    		}
    		// Set the window state to minimized will make the startup of PowerPoint much less intrusive.
    		_powerpointApp.Assistant.On = false// We don't want an assistant popping up...
    		_powerpointApp.SlideShowBegin += powerpointApp_SlideShowBegin;
    		_powerpointApp.SlideShowEnd += powerpointApp_SlideShowEnd;
    		_powerpointApp.SlideShowNextSlide += _powerpointApp_SlideShowNextSlide;
     
    		_hWndPowerPoint = (IntPtr)_powerpointApp.HWND;
    		if (_hwndHost != IntPtr.Zero)
    		{
    			AttachWindow(_hWndPowerPoint, _hwndHost, (IntPtr)Constants.HWND_TOP, Constants.SWP_HideWindow | Constants.SWP_DoNotChangeOwnerZOrder | Constants.SWP_IgnoreZOrder);
    		}
    	}
    	return _hWndPowerPoint != IntPtr.Zero;
    }
    


    Bart Roozendaal, Sevensteps Microsoft MVP for Surface

    • Proposed as answer by ValenciaJazz Friday, April 3, 2015 8:36 AM
    Sunday, January 5, 2014 3:05 PM