Solved

Microsoft Automation of MS-Word 2007 using VB.NET 2008 programming  COMException

Posted on 2013-01-14
11
1,748 Views
Last Modified: 2013-01-17
Hello EE Experts,

I am very suprised to see so few answered questions on the topic of Microsoft Automation of MS-Word using Visual Basic .NET (2008 in this case) programming there are on EE. The word "Automation" has a very special meaning in this context. So much benefit can be had in businesses of all sizes for the production of documents that are specific to the recipient -- not just junk mail. That is what my VB.NET 2008 program does. Produce documents for attorneys that have data inserted in them by the MS-Word Mail Merge process, but I am having a problem. After the document is produced and saved, I display the file name in a DataGrid that the user can click on to select and click on a  button to "open" the MS-Word document. This opens the document in MS-Word using MS-Word as what Microsoft calls an "Automation Server".

The problem that I am having is this. Early in the start up of the program I declare an object reference variable to point to an instance of MS-Word, and instantiate an instance of MS-Word using MS-Automation techniques. No big deal. Here is the code that works:

     Public go_wrdApp As Microsoft.Office.Interop.Word.Application
     go_wrdApp = CreateObject("Word.Application")

So now go_wrdApp is an object reference variable that points to an instance of the MS-Word.program (an Automation Server)

Using Microsoft "Automation" technique -- Each of the Microsoft Office program components can be a Microsoft "Automation Server" -- I can run the mail merge process and save each MS-Word document generated into a file to be opened later as described above. The problem occurs when the user closes the MS-Word application frame after looking at a documet by clicking on the red 'X' in the upper right corner of the application frame. This closes the whole instance of MS-Word -- not just the document that was being viewed in the application program.

So now, at a later time, when the same user attempts to look at another MS-Word document using the technique described above with the DataGrid, instead of opening the document in MS-Word the VB.NET 2008 program throws a COMException with the message "RPC server is unavailable" because the object reference variable go_wrdApp was left pointing at a MS-Word program object (Automation Server) that no longer exists because the user clicked on the little red 'X' in the upper right corner of the application frame instead of just closing only the document.

Is there a way that I can test "go_wrdApp" object reference variable to be sure that it is pointing at an instance of MS-Word program object that is really there?

"If Not IsNothing(go_wrdApp) Then" doesn't work.

Oh! I believe the reference to RPC in the error message means "Remote Procedure Call".

Thanks,
Ted Palmer
0
Comment
Question by:Ted Palmer
  • 7
  • 2
  • 2
11 Comments
 
LVL 42

Assisted Solution

by:sedgwick
sedgwick earned 250 total points
Comment Utility
its a twick but will work:

wrap try/catch around a call to some function in go_wrdApp (just to test the reference).
if you get COMException it means that reference is invalid and you need to re-create it using
go_wrdApp = CreateObject("Word.Application")
0
 

Author Comment

by:Ted Palmer
Comment Utility
Sedgwick,

Actually without intending to, I am already doing that twick. Except the Try/Catch block has a lot of source code in it and I didn't think of it as a twick at the time. But that doesn't mean that I can't create a small Try/Catch block just for that purpose. In another function I am already testing the error message returned for "RPC server is unavailable". If it tests true, I execute go_wrdApp = CreateObject("Word.Application") as you suggested. So I am coping with the issue already. I was just looking for something a little less convoluted. It appears that the method you suggest is probably the lease convoluted method there is. I'll try that later today. Unless somebody suggests a simpler method, you have the solution and the points.

Thank you for your help.

Ted Palmer
0
 
LVL 42

Expert Comment

by:sedgwick
Comment Utility
i know its not the best way of handling this issue but for me it saved alot of time and worked on the spot.
cheers
0
 
LVL 83

Accepted Solution

by:
CodeCruiser earned 250 total points
Comment Utility
Point 1:
You are using Office object model with early binding so CreateObject should not be used here as its used in late binding scenario

Change

Public go_wrdApp As Microsoft.Office.Interop.Word.Application
     go_wrdApp = CreateObject("Word.Application")

to

Public go_wrdApp As Microsoft.Office.Interop.Word.Application
go_wrdApp = New Microsoft.Office.Interop.Word.Application()





You can use following

go_wrdApp = Marshal.GetActiveObject("Word.Application")


to get reference to a running instance of Word. go_wrdApp will be Nothing if there is no instance running so then you can use If IsNothing to create a new instance

Public go_wrdApp As Microsoft.Office.Interop.Word.Application
go_wrdApp = Marshal.GetActiveObject("Word.Application")
If IsNothing(go_wrdApp)
   go_wrdApp = New Microsoft.Office.Interop.Word.Application()
End If
0
 

Author Comment

by:Ted Palmer
Comment Utility
CodeCruiser:

This looks more like what I was looking for. I just finished an SEO webinar and I have to run for an appointment. So I may not get to experiment with this suggestion till tomorrow, but you can be sure that I am going to try this.

Thank you so much,

Ted Palmer
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:Ted Palmer
Comment Utility
CodeCruiser:

I tried you suggestion and this is what I got. I'm adding a screen shot image of a stack trace and some code. The code first.

From the Logon_clicked event in the form Logon screen:

                    '2013-01-16 Ted Palmer
                    'Changed late binding to early binding per Experts-Exchange.
                    'go_wrdApp = CreateObject("Word.Application")
                    go_wrdApp = New Microsoft.Office.Interop.Word.Application()

From the PrintWord_Clicked event in a different form (screen):

        go_wrdApp = Marshal.GetActiveObject("Word.Application")

        '***** Debug Code -- Save 2013-01-14 by Ted Palmer
        If Not IsNothing(go_wrdApp) Then
            'Debug Code -- Save 2013-01-14 by Ted Palmer
            MessageBox.Show("go_wrdApp exists", _
            "AutoSubrogate® Debug Message:", MessageBoxButtons.OK, MessageBoxIcon.Stop)
            GoTo Exit_Point
        Else
            'Debug Code -- Save 2013-01-14 by Ted Palmer
            MessageBox.Show("go_wrdApp does NOT exists", _
            "AutoSubrogate® Debug Message:", MessageBoxButtons.OK, MessageBoxIcon.Stop)
            GoTo Exit_Point
        End If
MarshalDotGetActiveObject.JPG
0
 

Author Comment

by:Ted Palmer
Comment Utility
CodeCruser:

I tried your suggestion and this is what I got. I attached a screen shot of an error message screen from the general exception handler at the end of the Try/Catch for this block of code.

You can see in the first line of the stack trace that it referes to the Marshal.GetActiveObject("Word.Application"). I  have the "go_wrdApp = New Microsoft.Office.Interop.Word.Application()" statement in a different class. I didn't get an error message about  putting this statement in a different class to create the MS-Word program object.

Do I need to import this "System.Runtime.InteropServices" in the class where I do the "New" statement? I already added the import where I do the Marshal statement because I got a fatal error message requiring it.

The CLR message was "Operation unavailable".

Thanks for your help,

Ted Palmer
MarshalDotGetActiveObject.JPG
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
I don't know why that error is generated.

>go_wrdApp = New Microsoft.Office.Interop.Word.Application()

This is creating a new word instance anyway. In the class, you just declare the object (I don't know it needs to be in a separate class), then use marshal to get an existing instance and only create new instance if there is no existing instance.
0
 

Author Comment

by:Ted Palmer
Comment Utility
CodeCruser:

OK! I'll try that. Just FYI -- I may have to change this concept but the 'go_' in go_wrdApp stands for Global Object. It was my intent that I instantiate this program object at logon and make it available throughout the whole application program. I thought it would save some time not having to new up a MS-Word object everytime it was needed, but I have learned since the amount of time saved is trivial. I can be flexible.

Thanks for your help.

Ted Palmer
0
 

Author Comment

by:Ted Palmer
Comment Utility
CodeCruser & sedgwick:

I was able to instantiate the MS-Word program object as described by CodeCruser both ways:

By moving the "go_wrdApp = New Microsoft.Office.Interop.Word.Application()" into the same class where I was testing the object reference variable with "If Not IsNothing(go_wrdApp) Then" and after adding the import statement to the place from where I was originally instantiating it. But now that I have it instantiated I am having trouble Disposing of it. I guess I'm just not as good of OOP programmer as I thought I am. Anyway trying to reconcile this better method with what I already have in place that basicly works is taking way too much of my time. So I am going to have to split the points, and use sedgwick's method for now as an expediency.

Maybe next time I can start off doing it the better way in the beginning and not have problems disposing of the object when I am finished with it.

Thank you both for your help.

Ted Palmer
0
 

Author Closing Comment

by:Ted Palmer
Comment Utility
Thank you both. I appreciate your patience.

Ted Palmer
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now