Problem with office XP .NET interop assemblies

G

Guest

I'm trying to write an application that will allow an external device to be
synchronized with a PowerPoint presentation. So I wrote a very simple Windows
Forms application in C# that will load a PowerPoint presentation and get a
list of the slides. It then allows the user to hook each slide to an event on
the external device with the objective being that when that slide appears,
the external device should do a certain action. I'm using the office XP
primary interop assemblies from Microsoft and all of this works fine up to
this point.

Now I have a button that starts the actual presentation. My program will
handle the SlideShowNextSlide, SlideShowEnd and PresentationClose events
(from PowerPoint) and everything works great. My handler is triggered when
the slide changes and based on which slide is displayed, it makes the
external device do something.

The problem occurs after the presentation ends and I then try and restart
it. At this point when I get to the SlideShowSettings.Run() method I get a
COMException with the message "Presentation (unknown member) : Object does
not exist."

Does anybody have any idea what the problem here might be? I'm assuming that
something needs to be cleaned up on exit, but I've closed the presentation
with the Close() method and even tried reinitializing a whole new
PowerPoint.Application and PowerPoint.Presentation, but it just doesn't work.
 
S

Steve Rindsberg

I'm trying to write an application that will allow an external device to be
synchronized with a PowerPoint presentation. So I wrote a very simple Windows
Forms application in C# that will load a PowerPoint presentation and get a
list of the slides. It then allows the user to hook each slide to an event on
the external device with the objective being that when that slide appears,
the external device should do a certain action. I'm using the office XP
primary interop assemblies from Microsoft and all of this works fine up to
this point.

Now I have a button that starts the actual presentation. My program will
handle the SlideShowNextSlide, SlideShowEnd and PresentationClose events
(from PowerPoint) and everything works great. My handler is triggered when
the slide changes and based on which slide is displayed, it makes the
external device do something.

The problem occurs after the presentation ends and I then try and restart
it. At this point when I get to the SlideShowSettings.Run() method I get a
COMException with the message "Presentation (unknown member) : Object does
not exist."

Does anybody have any idea what the problem here might be? I'm assuming that
something needs to be cleaned up on exit, but I've closed the presentation
with the Close() method and even tried reinitializing a whole new
PowerPoint.Application and PowerPoint.Presentation, but it just doesn't work.

You mention that you've closed the presentation. If you do that, then your
Presentation object is nul so if you reference its properties/methodes, you'd
get an error much like what you're reporting.

That may or may not be it; w/o seeing the relevant bits of code, it's hard even
to guess.
 
A

Austin Myers

Have you tried looking in task manager after you close the presentation? My
bet is its still in memory and is running (or is locked up).



Austin Myers
MS PowerPoint MVP Team

Provider of PFCPro, PFCMedia and PFCExpress
www.playsforcertain.com
 
G

Guest

Thanks Austin and Steve for the replies.
I tried both closing and not closing the presentation in the
PresentationClose and SlideShowEnd events but it didn't seem to make any
difference. I also see PowerPoint show up in the process list when I first
open the presentation to read the slide descriptions, but it doesn't appear
in the task manager until the presentation actually starts. When the
presentation ends, it disappears from the task list, but remains in the
process list.

Here's some code:

' user clicks ppSelectButton first to to select a power point presentation
private void ppSelectButton_Click(object sender, EventArgs e)
{
if (powerpointOpenFileDialog.ShowDialog() == DialogResult.OK)
{
filename = powerpointOpenFileDialog.FileName;
powerpoint = new
Microsoft.Office.Interop.PowerPoint.Application();
ppt =
powerpoint.Presentations.Open(presentation.PowerPointPresentationFile,
Microsoft.Office.Core.MsoTriState.msoTrue,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse);
' populate a listbox with slide names
slideListBox.Items.Clear();
for (int i = 1; i <= ppt.Slides.Count; i++) // slide
numbers are 1 based instead of 0 based
{
string name = "";
if (ppt.Slides.Shapes.HasTitle ==
Microsoft.Office.Core.MsoTriState.msoTrue)
{
PowerPoint.Shape shape = ppt.Slides.Shapes.Title;
if (shape.TextFrame.HasText ==
Microsoft.Office.Core.MsoTriState.msoTrue)
{
name = shape.TextFrame.TextRange.Text;
}
}
' SlideInfo is just a class that holds info about that slide
SlideInfo si = new SlideInfo(ppt.Slides.SlideIndex,
name);
slideListBox.Items.Add(si);
}
}
}

private void startButton_Click(object sender, EventArgs e)
{
powerpoint.SlideShowNextSlide += new
PowerPoint.EApplication_SlideShowNextSlideEventHandler(powerpoint_SlideShowNextSlide);
powerpoint.SlideShowEnd += new
PowerPoint.EApplication_SlideShowEndEventHandler(powerpoint_SlideShowEnd);
powerpoint.PresentationClose += new
PowerPoint.EApplication_PresentationCloseEventHandler(powerpoint_PresentationClose);
this.SendToBack();
ppt.SlideShowSettings.Run();
}

void powerpoint_PresentationClose(PowerPoint.Presentation Pres)
{
EndShow();
}

void powerpoint_SlideShowEnd(PowerPoint.Presentation Pres)
{
EndShow();
}

private void EndShow()
{
multisniff.SetChannel(0);
this.BringToFront();
ppt.Close();
}
 
A

Austin Myers

When the presentation ends, it disappears from the task list, but remains
in the
process list.

I'm not well versed in C# so its a bit hard for me to follow your code.
However, I think the issue is that ppt is still a running process. Anytime
I've had that situation I can't fire a new instance (run another show).

I can't tell here but are you running GC (Garbage Collection) at some point?
If not that would be my first suggestion.


Austin Myers
MS PowerPoint MVP Team

Provider of PFCPro, PFCMedia and PFCExpress
www.playsforcertain.com
 
S

Steve Rindsberg

Thanks Austin and Steve for the replies.
I tried both closing and not closing the presentation in the
PresentationClose and SlideShowEnd events but it didn't seem to make any
difference. I also see PowerPoint show up in the process list when I first
open the presentation to read the slide descriptions, but it doesn't appear
in the task manager until the presentation actually starts. When the
presentation ends, it disappears from the task list, but remains in the
process list.

It sounds like Austin's on the right track.
I'm not a C-reader either but ...
' user clicks ppSelectButton first to to select a power point presentation
private void ppSelectButton_Click(object sender, EventArgs e)
{
if (powerpointOpenFileDialog.ShowDialog() == DialogResult.OK)

It appears that you're invoking PPT's Open File dialog here?
Meaning that you've got an instance of PPT running.

And then ...
{
filename = powerpointOpenFileDialog.FileName;
powerpoint = new
Microsoft.Office.Interop.PowerPoint.Application();

Invoking a new instance? But since PPT is not a multi-instance application, you'd have
two references to the same instance. Invoking close on the second instance would
release the reference to it but there'd still be the original reference, which would
hold the instance of PPT open.

Does that make sense, or am I (more probably) TOTALLY misunderstanding the code?

ppt =
powerpoint.Presentations.Open(presentation.PowerPointPresentationFile,
Microsoft.Office.Core.MsoTriState.msoTrue,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse);
' populate a listbox with slide names
slideListBox.Items.Clear();
for (int i = 1; i <= ppt.Slides.Count; i++) // slide
numbers are 1 based instead of 0 based
{
string name = "";
if (ppt.Slides.Shapes.HasTitle ==
Microsoft.Office.Core.MsoTriState.msoTrue)
{
PowerPoint.Shape shape = ppt.Slides.Shapes.Title;
if (shape.TextFrame.HasText ==
Microsoft.Office.Core.MsoTriState.msoTrue)
{
name = shape.TextFrame.TextRange.Text;
}
}
' SlideInfo is just a class that holds info about that slide
SlideInfo si = new SlideInfo(ppt.Slides.SlideIndex,
name);
slideListBox.Items.Add(si);
}
}
}

private void startButton_Click(object sender, EventArgs e)
{
powerpoint.SlideShowNextSlide += new
PowerPoint.EApplication_SlideShowNextSlideEventHandler(powerpoint_SlideShowNextSlide);
powerpoint.SlideShowEnd += new
PowerPoint.EApplication_SlideShowEndEventHandler(powerpoint_SlideShowEnd);
powerpoint.PresentationClose += new
PowerPoint.EApplication_PresentationCloseEventHandler(powerpoint_PresentationClose);
this.SendToBack();
ppt.SlideShowSettings.Run();
}

void powerpoint_PresentationClose(PowerPoint.Presentation Pres)
{
EndShow();
}

void powerpoint_SlideShowEnd(PowerPoint.Presentation Pres)
{
EndShow();
}

private void EndShow()
{
multisniff.SetChannel(0);
this.BringToFront();
ppt.Close();
}
 
G

Guest

Thanks Austin, but GC doesn't seem to help. I tried both GC.Collect and
Marshall.ReleaseComObject. This is really frustrating!
 
G

Guest

Thanks for your reply Steve but,

Steve Rindsberg said:
It sounds like Austin's on the right track.
I'm not a C-reader either but ...


It appears that you're invoking PPT's Open File dialog here?
Meaning that you've got an instance of PPT running.

No, powerpointOpenFileDialog is just what I decided to call my instance of
the .NET OpenFileDialog. I can see why it might be slightly confusing.
And then ...


Invoking a new instance? But since PPT is not a multi-instance application, you'd have
two references to the same instance. Invoking close on the second instance would
release the reference to it but there'd still be the original reference, which would
hold the instance of PPT open.

Does that make sense, or am I (more probably) TOTALLY misunderstanding the code?

I'm pretty sure I only have one instance of PPT running, but it's something
that's worth me double checking. I'll double check the code.
 
A

Austin Myers

Thanks Austin, but GC doesn't seem to help. I tried both GC.Collect and
Marshall.ReleaseComObject. This is really frustrating!

I know this is not what you want to hear but *something* is keeping PPT
open. It is VERY touchy about how you create the instance and if there is
ANYTHING in your code still happening it will not close out. (Been there
done that.)

My bet is that if you run your code and close PPT and then go to task
manager and manually kill the process thread everything will work again. At
least doing this will tell you if PPT is really closed or not.

Of course the trick now is figuring out what it is in your code that is
holding the process open. Is there a chance you have created two instances
of PPT? That would be my starting point in trying to nail it down.



Austin Myers
MS PowerPoint MVP Team

Provider of PFCPro, PFCMedia and PFCExpress
www.playsforcertain.com
 
S

Steve Rindsberg

No, powerpointOpenFileDialog is just what I decided to call my instance of
the .NET OpenFileDialog. I can see why it might be slightly confusing.

OK, never mind that then. ;-)
I'm pretty sure I only have one instance of PPT running, but it's something
that's worth me double checking. I'll double check the code.

I can guarantee that you only have one instance running (that's all PPT allows other than
under very unusual circumstances ... multiple users on the same PC at one time, for
example). But there might be multiple references to one instance; as long as the reference
is valid, the instance would stay alive.

As a test, maybe step through the code to where you're sure PPT should be gone, then look in
task manager's process list (not the app list) for PowerPnt.exe
 
G

Guest

Powerpoint is still in the process list and if I kill it there then I get
"The RPC server is unavailable" when I try and restart the presentation. So,
I guess that's some progress!
I'll have to mess with it some more.
 
A

Austin Myers

wjousts said:
Powerpoint is still in the process list and if I kill it there then I get
"The RPC server is unavailable" when I try and restart the presentation.
So,
I guess that's some progress!
I'll have to mess with it some more.


Ah the joys of .NET coding to unmanaged (Office) code. :-(



Austin Myers
MS PowerPoint MVP Team

Provider of PFCPro, PFCMedia and PFCExpress
www.playsforcertain.com
 

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