Consulting

Results 1 to 14 of 14

Thread: Is PowerPoint still a single instance app?

  1. #1
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location

    Is PowerPoint still a single instance app?

    As of Powerpoint 2000, it is my understanding that there can only be a
    single instance of Powerpoint running.
    Is that still true for Powerpoint 2002 and 2003?

    I've been using code such as the following:
    [vba]
    'Get existing instance of PowerPoint; otherwise create a new one
    ' Powerpoint is a single instance application
    On Error Resume Next
    Set appPPT = GetObject(, "PowerPoint.Application")
    If Err.Number = 0 Then
    blnNewPPT = False
    Else
    Set appPPT = New PowerPoint.Application
    blnNewPPT = True
    End If
    On Error GoTo 0
    [/vba]
    and then
    [vba]
    With appPPT
    If blnNewPPT Then
    .Quit
    Else
    .ActivePresentation.Close
    End If
    End With
    [/vba]
    However, I suspect that code may not be good enough.
    Do I not need to know whether the single instance of Powerpoint is being
    used by another user, even if I created the instance within the code?

  2. #2
    VBAX Master Killian's Avatar
    Joined
    Nov 2004
    Location
    London
    Posts
    1,132
    Location
    Hi Howard,

    I just ran a couple of quick tests on 2002 and 2003 and can't get a new instance of Powerpoint to launch with code from an existing one - which is a shame simce running another instance of an app in the background can be useful sometimes. Oh well, them's the breaks...
    K :-)

  3. #3
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Quote Originally Posted by Killian
    Hi Howard,

    I just ran a couple of quick tests on 2002 and 2003 and can't get a new instance of Powerpoint to launch with code from an existing one - which is a shame simce running another instance of an app in the background can be useful sometimes. Oh well, them's the breaks...
    The critical question is:

    Do I not need to know whether the single instance of Powerpoint is being
    used by another user, even if I created the instance within the code?
    I might create an instance of Powerpoint in code, and some user might start a Powerpoint session outside the code, so I cannot safely kill the instance I created.

  4. #4
    VBAX Master Killian's Avatar
    Joined
    Nov 2004
    Location
    London
    Posts
    1,132
    Location
    I see.

    Yes, you're quite right. A user launching PowerPoint will, in fact, activate your instance. I don't see there's anyway round that and since there's no new process thread for the user's action I don't see a way of detecting if it's happened.

    I guess all you can do is check the Presentations collection having tidied up your code driven stuff to see if there's anything left...?
    K :-)

  5. #5
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Quote Originally Posted by Killian
    I see.

    Yes, you're quite right. A user launching PowerPoint will, in fact, activate your instance. I don't see there's anyway round that and since there's no new process thread for the user's action I don't see a way of detecting if it's happened.

    I guess all you can do is check the Presentations collection having tidied up your code driven stuff to see if there's anything left...?
    It has ben suggested that if, instead of killing the powerpoint instance, if
    i just set it to Nothing, the instance of powerpoint will go away if there
    are no other powerpoint sessions.

    I'll try this later.

    I would feel comfortable relying on this only if I saw documentation of this
    behavior, and for powerpoint 97, 2000, 2002 and 2003.

    Not sure that behavior would work automating via VB .NET, but I have no plans to use the code in .NET.

    The last resort would be to lock the desktop momentarily. If the presentation count is 1, th kill the critter, otherwise let it live. This ASSuMEs that there is a different instance of powerpoint on each desktop on a multi-user system. Otherwise, kablooey!

  6. #6
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Came up with a "solution".
    Seems too simple to be correct.

    For the code below, one needs a Userform with 3 buttons.

    1. Shut down any running PowerPoint.
    2. Click on the Create PPT button.
    3. After the program creates a PPT session, create a PPT session via the GUI, not using the icon minimized by the code.
    4. Click on the Close PPT button.
    5. Click on the Bye Bye button.

    This code would appear to work for those cases in which my code need not keep a presentation alive. So, if I close all the code's presentations, this method appears to work.

    If I have to keep a presentation alive, that should be no problem as I just would not close PowerPoint, just set its object variable = Nothing.

    Does this hanky panky solve the problem?
      Option Explicit
    	Private appPPT As Powerpoint.Application
    	 Private blnNewPPT As Boolean
    '	Private MyPrivateName As String
       
      Private Sub btnByeBye_Click()
    	Unload Me
    End Sub
       
      Private Sub btnClosePPT_Click()
    	With appPPT
    		If blnNewPPT  Then
    			If .Presentations.Count = 0 Then
    				 .Quit
    				lstActions.AddItem "New instance was Quit."
    			Else
    				lstActions.AddItem "New instance was NOT Quit."
    			End If
    		Else
    			On Error  Resume Next
    			.ActivePresentation.Close
    			On Error  GoTo 0
    			lstActions.AddItem "Extant instance was not  Quit."
    		End If
    	End With
    	Set appPPT = Nothing
    	 lstActions.AddItem "Set instance = Nothing."
    	On Error Resume Next
    	 lstActions.AddItem Err.Number & ":" & Err.Description
    	On Error  GoTo 0
    End Sub
       
      Private Sub btnCreatePPT_Click()
    	'Get existing instance of  PowerPoint; otherwise create a new one
    	On Error Resume Next
    	Set  appPPT = GetObject(, "PowerPoint.Application")
    	lstActions.AddItem  Err.Number & ":" & Err.Description
    	If Err.Number = 0  Then
    		blnNewPPT = False
    		lstActions.AddItem "Extant instance  is being used."
    	Else
    		Set appPPT = New  Powerpoint.Application
    		blnNewPPT = True
    		lstActions.AddItem  "New instance was created."
    	End If
    	With appPPT
    '		 MyPrivateName = "HK" & Now & CDbl(Now)
    		.Visible =  True
    		.WindowState = ppWindowMinimized
    		lstActions.AddItem  "Presentations Count: " & .Presentations.Count
    	End With
    	On  Error GoTo 0
    End Sub

  7. #7
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    The "solution" does not detect a Powerpoint session that has no presentations, other than my own.

    Is there an API, or some such that can tell me a reference count, or whatever, number of powerpoint instances being used?

    I'm not yet ready to yell Uncle!


    P.S.: I've been using the wrong terminology. MSFT uses "multi-use" and I've been using "single use".

  8. #8
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    I've come up with the following, is it valid?

    1. Make sure that PowerPoint is not running.

    2. Run a VB 6 program that creates a NEW instance of PowerPoint.

    3. While the program in step 2 is still running, and PPT has not been Quit,
    run another VB 6 program that enumerates desktop processes, call the output List 1.

    4. While the PPT from step 2 is still running, start PowerPoint from the
    desktop. Since I had already created an instance in step 2, both should end
    up using the same instance as PowerPoint is multi-use, single instance.

    5. Now, again run the program that enumerates desktop processes, call the
    output List 2.

    Both List 1 and List 2 give the same handle for PowerPoint, and the same
    number of top level windows.

    List 1 does not list an active presentation, whilst List 2 lists
    Presentation1. So the first bit of info is that the caption PowerPoint window will include the latest use of Powerpoint. So this doesn't help solve my
    problem.

    However, the Total Thread Windows is 9 for List 1, 11 for List 2

    I am enumerating the processes using code based on KB article 183009 and
    only incrementing the counters when PP11FrameClass is found.

    So, is it safe to ASSuME that I can determine that there is another user
    using my PowerPoint object if the thread count is greater than the number
    reported by List 1?

  9. #9
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Not yet there, the code from the KB article is enumerating Windows, not processes, so doesn't handle case where presentation count = 0.

  10. #10
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Appears that I can do the deed by iterating processes.
    Needs further testing.

    Later tonight.

  11. #11
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Eureka, I think!

    I believe that I can demonstrate how to detect whether there is 1, or more
    than 1, use of Powerpoint, but I want to convert the code to C#, then VB
    .NET, then VB 6 before I post a test.

    This was interesting, but exhausting.

  12. #12
    VBAX Master Killian's Avatar
    Joined
    Nov 2004
    Location
    London
    Posts
    1,132
    Location
    Hi Howard,

    just to let you know I'm following your progress with great interest
    K :-)

  13. #13
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Quote Originally Posted by Killian
    Hi Howard,

    just to let you know I'm following your progress with great interest
    I now have code in C++ .NET, C#, VB .NET and VB 6 that provides the info needed to test my hypothesis.

    I need to try the code with PPT 97, 2000, 2002 and 2003 for validity.

  14. #14
    VBAX Mentor
    Joined
    Sep 2004
    Location
    Nashua, NH, USA
    Posts
    489
    Location
    Well, I've run a test in PowerPoint 97, 2000, 2002, and 2003.

    Same resuls in all four (with 1 exception in, surprise!, PPT 97),

    It appears that there's NEVER a REQUIREMENT to use Quit or to set the PPT
    object to nothing. Indeed, one can get in trouble doing so.

    Of course, one might wish to do so in the context of a larger/longer running
    app to free resources, BUT, as my headbanging these past few weeks has confirmed, it is NEVER safe to release a PPT object, especially if one's code created a NEW instance, as such an action could wipe other uses of PPT, in particualr thaose started by other code.

    The only case that bothers me is when you create a NEW non-visible instance of PPT in code AND then some other code creates another non-visible intance which adds a presentation (not visible because the PPT is not visible), if you shut down the code WITHOUT a QUIT, PPT goes away anyway. However, this does not occur with PPT 97. Idendependently of whether onelikes the idea of PPT affecting another session with a non-visible presentation, that's a rather significant difference between PPT 97 and later versions, You'd think that the Officve 2000 documentation would have pointed this out. Has it? I've not checked.

    The code I used for my test is given below, it's a hack, so it's not pretty.

    Put the code in a VB 6 Form, you could tweak the code and run it from other apps, but NOT from PowerPoint.

    Form has 7 buttons and 1 listbox:

    btnPPTNew: "Create New PPT"
    btnQuitNewPPT: "Quit New PPT"
    btnPPTVisible: "Start a Visible PPT"
    btnPPTNonVisible: "Start a Non-Visible PPT"
    btnPPTNonVisibleWithPresentation: "Start a Non-Visible PPT with
    presentation"
    btnByeBye: "ByeBye!"
    btnClearList: "Clear List"

    lstActions

    A file named PPTTest.txt is created in the directory in which the code is
    executed.

    Use the Task Manger to watch when PowerPoint is created/deleted.
    ' Author: Howard Kaikow
    ' Author URL: http://www.standards.com/
    ' Date: 12 June 2005
    Option Explicit
    	Private Const LB_SETHORIZONTALEXTENT = &H194
    	
    	Private Declare Function SendMessage Lib "user32" Alias _
    		"SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _
    		ByVal wParam As Long, lParam As Any) As Long
    	
    	Private appPPTOriginal As PowerPoint.Application
    	Private appPPTVisible As PowerPoint.Application
    	Private appPPTNonVisible As PowerPoint.Application
    	Private appPPTNonVisibleWithPresentation As PowerPoint.Application
    	
    	Private intFile As Integer
    
    Private Sub btnPPTNonVisibleWithPresentation_Click()
    	Dim presPPT As PowerPoint.Presentation
    	On Error Resume Next
    	Set appPPTNonVisibleWithPresentation = GetObject(, "PowerPoint.Application")
    	If Err.Number = 0 Then
    		Print #intFile, "PowerPoint: Another non-Visible, with presentation, instance was created."
    		lstActions.AddItem "PowerPoint: Another non-Visible, with presentation, instance was created."
    		Debug.Print "PowerPoint: Another non-Visible, with presentation, instance was created."
    		Set presPPT = appPPTNonVisibleWithPresentation.Presentations.Add
    	Else
    		Print #intFile, "PowerPoint: Another non-Visible, with presentation, Huh!"
    		lstActions.AddItem "PowerPoint: Another non-Visible, with presentation, Huh!"
    		Debug.Print "PowerPoint: Another non-Visible, with presentation, Huh!"
    	End If
    	On Error GoTo 0
    	btnPPTNonVisibleWithPresentation.Visible = False
    End Sub
    
    Private Sub btnPPTNew_Click()
    	On Error Resume Next
    	'Check if PowerPoint is running
    	Do
    		Set appPPTOriginal = GetObject(, "PowerPoint.Application")
    		If Err.Number = 0 Then
    			If vbCancel = MsgBox("Stop all running instances of PowerPoint, and then choose Retry to continue this test." _
    			 & vbCrLf & vbCrLf & "Or choose Cancel to cancel this test.", vbInformation + vbRetryCancel, "PowerPoint is currently running") Then
    				Unload Me
    				Exit Sub
    			End If
    		Else
    			Err.Clear
    			Exit Do
    		End If
    	Loop
    	' Verify that PowerPoint is still not running
    	Set appPPTOriginal = GetObject(, "PowerPoint.Application")
    	If Err.Number = 0 Then
    		MsgBox "PowerPoint is still running", vbInformation + vbOK, "Test cancelled"
    		Unload Me
    	Else
    		Set appPPTOriginal = New PowerPoint.Application
    		Print #intFile, "PowerPoint: New non-visible instance was created."
    		lstActions.AddItem "PowerPoint: New non-visible instance was created."
    		Debug.Print "PowerPoint: New non-visible instance was created."
    		btnPPTNew.Visible = False
    		btnPPTVisible.Visible = True
    		btnPPTNonVisible.Visible = True
    		btnPPTNonVisibleWithPresentation.Visible = True
    		btnQuitNewPPT.Visible = True
    	End If
    	On Error GoTo 0
    	btnClearList.Visible = True
    End Sub
    
    Private Sub btnPPTVisible_Click()
    	On Error Resume Next
    	Set appPPTVisible = GetObject(, "PowerPoint.Application")
    	If Err.Number = 0 Then
    		Print #intFile, "PowerPoint: Visible instance was created."
    		lstActions.AddItem "PowerPoint: Visible instance was created."
    		Debug.Print "PowerPoint: Visible instance was created."
    		appPPTVisible.Visible = True
    	Else
    		Print #intFile, "PowerPoint: Visible Huh!"
    		lstActions.AddItem "PowerPoint: Visible Huh!"
    		Debug.Print "PowerPoint: Visible Huh!"
    	End If
    	On Error GoTo 0
    	btnPPTVisible.Visible = False
    End Sub
    
    Private Sub btnPPTNonVisible_Click()
    	On Error Resume Next
    	Set appPPTNonVisible = GetObject(, "PowerPoint.Application")
    	If Err.Number = 0 Then
    		Print #intFile, "PowerPoint: Another non-Visible instance was created."
    		lstActions.AddItem "PowerPoint: Another non-Visible instance was created."
    		Debug.Print "PowerPoint: Another non-Visible instance was created."
    	Else
    		Print #intFile, "PowerPoint: Another non-Visible Huh!"
    		lstActions.AddItem "PowerPoint: Another non-Visible Huh!"
    		Debug.Print "PowerPoint: Another non-Visible Huh!"
    	End If
    	On Error GoTo 0
    	btnPPTNonVisible.Visible = False
    End Sub
    
    Private Sub btnQuitNewPPT_Click()
    	If TypeName(appPPTOriginal) = "Application" Then
    		With appPPTOriginal
    			If .Presentations.Count = 0 Then
    			 Print #intFile, "PowerPoint: (0)New non-visible instance was Quit."
    			 lstActions.AddItem "PowerPoint: (0)New non-visible instance was Quit."
    			 Debug.Print "PowerPoint: (0)New non-visible instance was Quit."
    			Else
    			 Print #intFile, "PowerPoint: (not 0)New non-visible instance was Quit."
    			 lstActions.AddItem "PowerPoint: (not 0)New non-visible instance was Quit."
    			 Debug.Print "PowerPoint: (not 0)New non-visible instance was Quit."
    			End If
    			.Quit
    			Set appPPTOriginal = Nothing
    		End With
    		btnQuitNewPPT.Visible = False
    		Unload Me
    	End If
    End Sub
    
    Private Sub Form_Load()
    	btnClearList.Visible = False
    	btnPPTVisible.Visible = False
    	btnPPTNonVisible.Visible = False
    	btnPPTNonVisibleWithPresentation.Visible = False
    	btnQuitNewPPT.Visible = False
    	intFile = FreeFile
    	Open "PPTTest.txt" For Output As #intFile
    End Sub
    	   
    Private Sub Form_Activate()
    	With lstActions
    		SendMessage .hWnd, LB_SETHORIZONTALEXTENT, _
    			ScaleX(.Width, vbTwips, vbPixels) + 150, ByVal 0&
    	End With
    End Sub
    
    Private Sub btnByeBye_Click()
    	Dim PPTCount As Long
    	QuitPPT
    	Unload Me
    End Sub
    
    Private Sub QuitPPT()
    	If TypeName(appPPTOriginal) = "Application" Then
    		With appPPTOriginal
    			' Non-visible uses of PowerPoint added AFTER this code created NEW non-visible
    			' instance get killed if there is no VISIBLE use of PowerPoint.
    			If .Presentations.Count = 0 Then
    			 Print #intFile, "PowerPoint: (0)New non-visible instance was NOT Quit."
    			 lstActions.AddItem "PowerPoint: (0)New non-visible instance was NOT Quit."
    			 Debug.Print "PowerPoint: (0)New non-visible instance was NOT Quit."
    			Else
    			 Print #intFile, "PowerPoint: (not 0)New non-visible instance was NOT Quit."
    			 lstActions.AddItem "PowerPoint: (not 0)New non-visible instance was NOT Quit."
    			 Debug.Print "PowerPoint: (not 0)New non-visible instance was NOT Quit."
    			End If
    		End With
    	End If
    End Sub
    
    Private Sub btnClearList_Click()
    	lstActions.Clear
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
    	On Error Resume Next
    	Close #intFile
    	On Error GoTo 0
    End Sub

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •