Is Powerpoint still a single instance app?

H

Howard Kaikow

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:

'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
and then

With appPPT
If blnNewPPT Then
.Quit
Else
.ActivePresentation.Close
End If
End With

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?
 
H

Howard Kaikow

Steve Rindsberg said:
Still true. All versions from 97 on are devoutly single-instance.

Should "devoutly" be "devilishly"?
A few things that might help distinguish between a session you invoked from
scratch and a reference to an existing session:

With app.PPT
if .Presentations.Count = 1 Then
if .Presentations(1).Path = "" and _
.Presentations(1).Name = "Presentation1" Then
' it's your session or
' somebody started PPT but hasn't done anything yet
End If
End if

End With

Ayup, I thought about those, but the real issue is control.
If I decide that I own the session and nobody else is using powerpoint,
there is still an instant or so, during which I'd be killing the critter and
somebdy might have just started a session.

I run only in a single user environment, so I cannot test some concerns?

Is the single instance of PowerPoint system wide, or is it on a desktop by
desktop basis, on a multi-user system?
If the latter, I could disable the desktop whilst I kill the critter.
 
H

Howard Kaikow

Steve Rindsberg said:
That depends on whether you want to have multiple instances or to be certain of
which instance you have. ;-)

The goal is to automate powerpoint from word in an a vb 6 program.
once the task is done, there's no need to retain the powerpoint instance,
not unlike a multi-use app, i.e., it's bad to allow instances of multi-use
apps to be left active.
Point taken, and it'd be better to head that off at the pass if possible.
Still, in that case the worst that'd happen is that the new session wouldn't
start. I can't tell you how often I'm sure I doubleclicked something but got
no reaction, oh well, try again. Wouldn't this appear to be one of those? In
other words, it might be very mildly puzzling, surely far less than normal
Windows behavior can be, but wouldn't cause any loss of data.

I guess the best I can do, is lock the desktop momentarily, and check the
Presentations count.
If = 1, then I'd quit powerpoint, otherwise, I'd let it live and be
visible.

Of course, visibility is another issue.

If I created the instance with GetObject, instead of NEW, I'd have to take
care not to make powerpoint invisible if some else is udsing the critter.
It would almost have to be on a desktop by desktop basis, else PowerPoint would
be stumbling all over itself whenever two users had it active. Same would be
true of any app I'd think. Not so much true of the app, in fact, but a
question of whether Windows permits them to see one another. It'd have to be
keeping them all (and each user's session) in separate memory spaces wouldn't
it?

That's what I would think.
I'll code as if that were true, i.e., lock the desktop while using a NEW
powerpoint instance.
 
H

Howard Kaikow

It has ben suggested that id, instead og 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 powerpont 97, 2000, 2002 and 2003.
 
H

Howard Kaikow

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
 
H

Howard Kaikow

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?

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

Howard Kaikow

i stumbled upon a possible solution last night.
i'll try to verify later today or tonight.
 
H

Howard Kaikow

http://www.standards.com/; See Howard Kaikow's web site.
Steve Rindsberg said:
Depending on user settings and version, PPT may automatically create a blank
presentation on startup, so presentation count might be 0 or 1 even if you've
invoked it. That's why I suggested the other rigamarole re checking the
presentation's name (always Presentation1 until it's been saved) and the path
(blank until it's been saved).

Yes, I realize that, and there may even be no presentation.
That's why I'm trying the following.
-------------------------
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 PowerPoint window will
be that of 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?
 
H

Howard Kaikow

Steve Rindsberg said:
Howard,

What about iterating through the current window collection before attempting to
get a PPT object; if any of the windows belong to PowerPoint, then somebody's
using it.

See my posting of a few minutes ago where I enumerated processes.
The sticky point is that my New instance of PPT is still open when I do the
iterations, i.e., I'm trying to determine whether I can Quit.

I am hoping that I can do this based on the thread count, as discussed in my
other posting.

it is necessary to do this iterating only if the presentation count is 0, as
i have already closed my, if any, presentation.
 
H

Howard Kaikow

Not yet there, the code from the KB article is enumerating Windows, not
processes, so doesn't handle case where presentation count = 0.
 
H

Howard Kaikow

Steve Rindsberg said:
Having fired off your own instance of PPT, how can you be certain that a user
hasn't in the interim invoked PPT on their own?

If you know that you started by invoking PPT when it wasn't previously open,
then you should also be able to maintain a count of any presentations you've
opened or created; if someone manually starts/opens another presentation, then
Presentations.Count will be higher than your total, so it wouldn't be safe to
force PPT to quit.

Does that oonch us a bit closer? ;-)

No.

Because the presentation count could still be 0.

Enumerating processes appears to resolve the problem, but I want to simplify
the code.
 
H

Howard Kaikow

Steve Rindsberg said:
Possibly for that instant, but closing an instance of PPT with no open
presentations will do no harm.

It sure does.

It closes the other uses of PPT.
Users, and other code, whould not be very ubhappy if theirPPT suddenly
disappeared.

To restate the problem.
----------------------------
I was using the wrong terminology.

PowerPoint is a Multi-use, single Instance app.

Assume that PPT is not running.

Then my code creates a NEW instance of PPT.
Then, while my code is running, PPT is again started by a user from the
desktop or via another piece of code.
Etc.

AFAIK, it is possible for all uses of PPT to have, at any point in time, a
Presentations.Count of 0, so I cannot tell whether I should Quit my instance
of PPT, based on Presentation count, lest it affect the other uses.

At some point, I would do the following:

1. DoEvents
2. Disable keyboard and mouse input
3. test for number of PowerPoint critters.
4. If only 1 critter, Quit PPT, otherwise let it live.
5. Enable keyboard and mouse input
6. exit from my code.

Enumerating processes, using say, the example at ALLAPI, lists a different
working set size for each use of PPT.

In my case, all I need to know is whether there is one use or more, does not
matter how many. If 1 use, then I can safely Quit my instance of Powerpoint.

I need to study the ALLAPI, and other examples, to make sure the info is
what I need.
 
M

Mike M.

My app has been doing what Steve suggests for almost 4 years without any
reports of problems. There is one and only one instance of Powerpoint
(powerpnt.exe) running regardless of how many programs have a reference
count to it or if a user opened the GUI for Powerpoint. I check to make
sure that presentations count <= 0 then I call the Powerpoint quit method.
If a user has started the GUI and closed the pres1 (or whatever) default
presentation Powerpoint creates then indeed when you quit PowerPoint it
closes the GUI. If other programs have connected to that instance of
Powerpoint then they would get an exception when they referenced that
object. But that is why there is a big disclaimer on the MS web site that
tells us not to use Powerpoint in an automated fashion. We are pretty much
out there on our own. I had originally hoped they would expose the
reference count through a method or property but I didn't see it.

Good luck.
 
H

Howard Kaikow

Mike M. said:
My app has been doing what Steve suggests for almost 4 years without any
reports of problems. There is one and only one instance of Powerpoint
(powerpnt.exe) running regardless of how many programs have a reference
count to it or if a user opened the GUI for Powerpoint. I check to make
sure that presentations count <= 0 then I call the Powerpoint quit method.
If a user has started the GUI and closed the pres1 (or whatever) default
presentation Powerpoint creates then indeed when you quit PowerPoint it
closes the GUI. If other programs have connected to that instance of
Powerpoint then they would get an exception when they referenced that
object. But that is why there is a big disclaimer on the MS web site that
tells us not to use Powerpoint in an automated fashion. We are pretty much
out there on our own. I had originally hoped they would expose the
reference count through a method or property but I didn't see it.

It seems that the problem can be solved by enumerating processes.
 
M

Mike M.

Steve, I think this terminology goes against the grain. Sort of like
Unicast and Multicast in streaming video. MultiUse means that multiple
users attach to the single instance server. SingleUse means each user gets
their own instance of the server. AHA?
 
H

Howard Kaikow

Steve Rindsberg said:
Thanks, Howard. That still leaves me puzzled, though.

It refers to "Instancing" as having one of two values, Single- or MultiUse. It
doesn't refer to Instancing as a property distinct from those two.

And either I'm missing the kick in the head that triggers the AHA or the
article is wrong. It says:

"Depending on whether the server is designed as SingleUse or MultiUse, another
server process may or may not be launched." It doesn't say which is which, but
it seems reasonable to assume that "MultiUse" = "another server may be
launched".

It then goes on to say that Excel and Word are SingleUse, which doesn't seem
right to me. Rather, it seems to have reversed the values.

It does raise an interesting point that reinforces your thoughts, though:
we've been talking about user- and your_code-initiated instances of PPT, but
there might also be an instance initiated by the user or code activating a PPT
object (slide or presentation) from within another app.

The fun never ends. ;-)

If it's possible to identify and stop individual processes independent of the
application instance itself, it sounds as though you're onto a possible
solution to the problem.

Yes, MSFT's terminology can be confusing.
I added to the confusion by initially using the wrong terminology.
MSFT appears to use that terminology consistently in various KB articles.

In effect, it means that for PowerPoint, there is a single instance of the
program running, as you can see if you look at the Task Manager, but there
may be multiple uses of that instance.

For, say Word, you can have multiple instances of Word running, which you
can see in the Task Manager.

After my code works with Powerpoint, if the code has created a NEW instance
of PowerPoint, i.e,, no other PPT had been running, then the code has to
determine whether it is safe to Quit PPT. I only do this, because in the
code of interest, I have no need to leave any Presentation active. For the
latterm the issue is not relevant, I'd just let PPT live!

At some point, I need to examine the running processes to determine whether
anybody else started using PPT AFTER I created the NEW instance.

The logic of the solution is straight-forward.
The only issue is how to do it.

I found a number of examples in the MSFT KB, one at ALLAPI, and one in Steve
Roman's API book that demonstrate how to use EnumProcesses, so I think I
can do this.

One disappointment is that PSAPI.DLL is supported only on NT/2000/XP.
Other mechanisms are available for Win 95/Win 98/Win Me.

Unfortunately, I no longer have a Win 98 system and my ancient Win 95 system
does not have the resources to run a VBA version of PPT. So, I will include
code to detect the OS and prevent the PPT stuff from runniing on other OS,
or warn the user that they cannot run code that starts PPT until AFTER my
PPT code has completed, unless PPT was already running.

I'll be disabling keyboard and mouse input during the interval my code needs
to decide whether to Quit PPT, so the user will not be able to start PPT
from the desktop during the very short interval my code is deciding whether
to Quit PPT.

Yes, I am a masochist!
 
H

Howard Kaikow

Mike M. said:
Steve, I think this terminology goes against the grain. Sort of like
Unicast and Multicast in streaming video. MultiUse means that multiple
users attach to the single instance server. SingleUse means each user gets
their own instance of the server. AHA?

Terminology is in the eye of the beholder, heck, I still think that "PC"
means "plug compatible", not "imPersonal Computer".
 
M

Mike M.

I also use C++ to automate PowerPoint and initially I was having a problem
with getting PowerPoint to go away after I closed my reference to it. That
was using PPT 2000. I didn't have any trouble (well, that specific trouble)
once I started using PPT 2002. I vaguely remember thinking there was a
problem with the reference counting in that version of PPT but it might just
be a bad sector in my memory or bad programming. I am becoming more
susceptible to both.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top