Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Use an existing instance of Word from within VB .NET (2008)

Posted on 2010-01-07
14
Medium Priority
?
1,462 Views
Last Modified: 2013-11-26
I am trying to automate the creation of a Word document from an existing template and populate with data from a selected record. If possible I want to use an existing instance of Word so that the user doesn't end up with multiple instantiations which then have to be closed individually.
In Access VBA I could do this with the following code:

    Dim WordApp As Word.Application
    Set WordApp = GetObject(, "Word.Application")
    If Err.Number <> 0 Then
        Set WordApp = CreateObject("Word.Application")
    End If
    On Error GoTo ErrPoint
    WordApp.Documents.Add Template:="C:\Somewhere\Template.dot", NewTemplate:=False

This approach doesn't seem to work in VB .NET; the best I can do is this:

        Dim wordApp As Microsoft.Office.Interop.Word.Application
        On Error Resume Next
        wordApp = New Microsoft.Office.Interop.Word.Application
        On Error GoTo ErrPoint
         wordApp.Documents.Add(Template:=:="C:\Somewhere\Template.dot", NewTemplate:=False, DocumentType:=0)

But this seems to force the creation of a new instance of Word, with no possibility of piggybacking on an existing instance.
Once the document has been populated, it is then made visible to the user, who can save it somewhere if desired, or just close it. But when the Word session is closed, the message:
<<This file is in use by another application or user. (C:\Documents and
Settings\...\Normal.dot")>> appears and Word refuses to close. This can only be resolved by saving the normal.dot template under another name (normal1.dot).

So I have two problems: first I can't use an existinf Word instance (tiresome but not the end of the world) and second the user can't close Word (not acceptable) - I don't know if the second is a direct result of the first, but it never occurred in Access VBA. Why doesn't my version of VB .NET utilise the GetObject / CreateObject operators (I've seen various posting about earlier version of VB .NET and they all seem to use the GetObject/CreateObject approach), and when (and why) did the Interop prefix become necessary when defining the Word object?

Any ideas?
0
Comment
Question by:JeremyHigginson
  • 8
  • 6
14 Comments
 
LVL 9

Expert Comment

by:Hawkvalley1
ID: 26203966
I don't like the CreateObject method (though still available) as it is harder to dispose of it you do it manually - if they close it [X] that is fine. I use this format (class objects):
Private oWord As Microsoft.Office.Interop.Word.Application = Nothing
Private oDoc As Microsoft.Office.Interop.Word.Document = Nothing

Then when I open the template:
oWord = New Microsoft.Office.Interop.Word.Application
oDoc = New Microsoft.Office.Interop.Word.Document
oDoc = oWord.Documents.Add("your\File\Path.dot")

Since they class level you can call them later for same document. Word process can be hard to kill, so to guarantee disposal I use the sub below:

Private Sub ReleaseObject(ByVal o As Object)
    Dim i As Integer
    If Not o Is Nothing Then
      Try
        i = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
        While i > 0
          i = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
        End While
      Catch
      Finally
        o = Nothing
      End Try
    End If
End Sub

Any of this help?
0
 

Author Comment

by:JeremyHigginson
ID: 26204489
Thanks very much for the feedback. I'll make use of the disposal subroutine, but the main problem I have is that the Word session remains active after I've finished running my code, so that the user can view the open document. Whilst my code may be able to dispose of the object from the point of view of my app, the Word session is still running and it is when the user tries to close the Word session (independently of my app) that the problem occurs with the normal.dot template. #

I've seen lots of references to this problem, and indeed over the years I've encountered it in other (non-coding) situations. If I could understand more about what causes it, I might be able to prevent it. The text describing the error message is:
***************************
This error is commonly encountered when a read lock is set on the file you are attempting to open. This can be caused by:
Another user has the file open either on the same computer you are using or on another computer.
Word crashed at some point in the past and left a read lock on the file.
Another application has an exclusive lock on the file, which would not allow Word to open the file.
A custom application is running and has opened this file (possibly on another user's computer). It may have opened the file using an incorrect method.
To correct this problem, close all applications, restart Word and try to open this file again. If this does not work, examine the properties of the file to determine if someone else has it open. Occasionally a phantom process (dead or disassociated program) may have a lock on the file, and the only means of clearing it is to restart your computer.
***********************
The implication is that some other part of Word has placed a lock on the normal.dot template file (which I understand is used by default whenever Word starts up), but when the session closes I don't understand why the app is trying to write something back to that template file. This appears to be stored in the folder: <<C:\Users\Jeremy Higginson\AppData\Roaming\Microsoft\Templates>>, but if you try to save back to this file, it says it is read only - hence I get round this problem by saving to a random file I created called normal1.dot. Then I can close Word.

Maybe there is something about the parameters I pass to Word either when it is instantiated [wordApp = New Microsoft.Office.Interop.Word.Application] or when I create the document based on the template [wordApp.Documents.Add(Template:=:="C:\Somewhere\Template.dot", NewTemplate:=False, DocumentType:=0]. The latter seems  more likely, but it is essentially the same statement as was used in VBA, when I never had this problem. Incidentally, all references to the document are made as wordApp.ActiveDocument, and not via a specifically instantiated document object; but since I've used this approach in both the VBA case and the .NET case  I don't think this can be relevant.

Incidentally, I can still run the Access version of this on the same PC, also using Word 2003, and I experience no problems with closing Word.
0
 
LVL 9

Expert Comment

by:Hawkvalley1
ID: 26204893
I think your program has rights to it when they are trying to close it independant of the app, 1 poss solution is to disable the close button - but if they close your program -> dispose of the object -> and enable the close button. I am currently looking into this myself. See if this helps:

http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_24549702.html?sfQueryTermInfo=1+button+close+disabl+word

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 9

Expert Comment

by:Hawkvalley1
ID: 26204998
The above is for an open document side-by-side with app. Are you saying your document is not visible and running and then they try to open it from it's location?
0
 

Author Comment

by:JeremyHigginson
ID: 26205182
Hi Hawkvalley1

The app displays a list of projects, the user can select one to view and then display the details by clicking on a button. The "display" operation within my app puts the project details into a Word document based on a template, which is made visible to the user by the app, and the user can then (indepednetly of the app) save the Word document, print it, or just close Word and dispose of it. The app continues to be available for whatever activity they next want to perform.
0
 

Author Comment

by:JeremyHigginson
ID: 26205280
I've done a search of Microsoft support and there is the following article:

http://support.microsoft.com/kb/953579

It describes the cause as follows:
When you use a Word template to export a document, to print a document, or to send an e-mail in Microsoft Office Accounting Professional, in Microsoft Office Accounting Express, or in Microsoft Office Small Business Accounting 2006, you receive the following error message:
The file is in use by another Application or user. (path\Normal.dot)

And the resolution is as follows:
To resolve this problem, shut down the other instances of Word. To do this, follow these steps:
Close all open instances of Word and all applications that use Word, such as Microsoft Office Accounting Professional, Microsoft Office Accounting Express, Microsoft Office Small Business Accounting 2006, or Microsoft Outlook.
Click Start, click Run, type taskmgr, and then click OK.
On the Processes tab, click WINWORD.EXE, and then click End Process.
Click Yes.

Of course in my situation this isn't terribly helpful, but it does point the finger at the fact that the problem relates to running more than one instance of Word. (Even if there isn't an obvious instance running, it could have been initiated by Outlook if you have selected Word as your email editor of choice.)

So if anyone can tell me how to piggyback on an existing Word instance in VB .NET 2008 that would be really helpful.
0
 

Author Comment

by:JeremyHigginson
ID: 26205293
Sorry, the cause for this problem is described by Microsoft as : "This problem occurs when more than one instance of Word tries to open the same Normal.dot template."
0
 
LVL 9

Expert Comment

by:Hawkvalley1
ID: 26206296
It must be the way you call the doc in your '.Add statement.' I can open multiple docs from the same template. Also the ReleaseObject Sub will definitely help close those pesky processes. My add statement: oDoc = oWord.Documents.Add("path\to\your\file.dot").
   
HTH
Don
0
 

Author Comment

by:JeremyHigginson
ID: 26208214
Hi

1) These are the statements I am now using (as far as I can see, identical to yours):
        Dim wordApp As Microsoft.Office.Interop.Word.Application = Nothing
        Dim wordDocument As Microsoft.Office.Interop.Word.Document = Nothing
        Dim wordBookmark As Microsoft.Office.Interop.Word.Bookmark
        ......  
        wordApp = New Microsoft.Office.Interop.Word.Application
        wordDocument = New Microsoft.Office.Interop.Word.Document
        wordDocument = wordApp.Documents.Add(Template:=CStr(DocumentLocation))
        ......  
        For Each wordBookmark In wordDocument.Bookmarks
            Select Case wordBookmark.Name
                Case Is = "ApplicationName"
                    wordBookmark.Range.Text = DBGetTextNA(CStr(ApplicationTitle))
                 .......
        Next wordBookmark
        .......
        wordApp.Visible = True
        wordApp = Nothing
        ReleaseObject(wordApp)

All of the code to populate the document derived from the template is the same as it was in Access, so I know that there is nothing fundamentally wrong with it. But it still causes problems.

2) First of all, I have rebooted my PC so that no other Word processes can be running, then started Visual Studio, and my app in debug mode. Now when I select the menu option to generate the Word document, display the Word session and the document on screen, and then (as a user) save the document and close the Word session, I get no error message.

3) This clearly indicates to me that when there is an existing Word session running, it has locked the normal.dot template file; when I start up my parallel Word session and it tries to close itself and save to the normal.dot template file, it cannot do so. When there is no other Word session running, the problem does not occur.

4) Even if I close my VB app first and then close the Word session (whilst another one is running in parallel), I still get the problem.

5) The person who is testing this at their own (health sector) site has exactly the same problem so it is not unique to my PCs or local setup.

So I'm still stuck!

0
 
LVL 9

Accepted Solution

by:
Hawkvalley1 earned 1000 total points
ID: 26210060
Are you opening a Word Template or one of your own custom built templates? If you are using Word's, try building you own - this may be where I am not running into the same problem, and this might fix yours.

Not that this should matter, yours:
wordDocument = wordApp.Documents.Add(Template:=CStr(DocumentLocation))
mine:
wordDocument = wordApp.Documents.Add("C:\path\to\your\file.dot")

You set it up just like I was going to suggest minus the part of setting the word object to nothing prior to the ReleaseObject Sub - this will call that anyway.

Sounds like you watching the Processes in the Task Manager - look before and after you creates the doc. Make sure there are no other places in code that opens a Word process. ReleaseObject may or may not close a process opened by CreateObject(). Try opening just one, release it and check for the process. I have not seen anytime where my RelesaeObject has failed to do its job. I use Vista, but could test on XP, I am using Word 2007 with 97-2003 templates with no issues. And use the References: Word 12.0 object library, Visual Basic for appl. extensibilty 5.3, & Office 9.0 object library.

Sorry for your frustration,
HTH
Don

0
 

Author Comment

by:JeremyHigginson
ID: 26211799
Hi again

Ultimately there's some good news, but first....

I tried the tweak to the wordDocument = code line, but  no luck.

Then I dug around and found a Microsoft support article (http://support.microsoft.com/default.aspx?scid=kb;en-us;285885) dealing with "Prompt to save Normal.dot when using Word as an automation server". It suggests two things:

1) Before you quit Word or transfer control to the user, set the Saved property of the Normal.dot template to True as follows:
Application.NormalTemplate.Saved = True
2) Set the SaveChanges argument for the Quit method as follows:
Application.Quit SaveChanges:=wdDoNotSaveChanges

The second one isn't relevant for me as I'm not quitting the Word session, but I put the line of code in for the first option.

Then I tried it on my development PC and - same as before! Then I found an MSDN article (http://msdn.microsoft.com/en-us/library/h1e6ht9c(VS.80).aspx), which contained the following text:

Word Locks Normal.dot While Open in Visual Studio
-------------------------------------------------------------
When Word is open in Visual Studio, it locks the default template Normal.dot. When you run your solution for debugging, a copy of Word is opened in another process. If you make application-level customizations to the open copy of Word, such as modifying the toolbars or menus, you cannot save those changes because Normal.dot is locked by the process that is open inside Visual Studio.
At run time, Word opens separate instances of documents in a single process, so it is not as likely that one open document will lock Normal.dot and prevent application-level changes.
For more information, see the Knowledge Base article "PRB: Prompt to Save Normal.dot When Using Word as an Automation Server" (http://support.microsoft.com/default.aspx?scid=kb;en-us;285885).

So it pointed me back to the article I'd previously found, but I thought I would try it out after I'd built my project and installed it on another test PC, and allelujah it worked!!

Now I don't know which of the changes I made actually caused the problem to go away (since I didn't think to do any testing idependently of my Visual Studio environment) - it could have been yours or it could have been Microsoft's. But I haven't currently got the strength to remove them one by one until it fails again, so I think it's only fair to give you the points anyway.

0
 

Author Closing Comment

by:JeremyHigginson
ID: 31674161
Thanks for staying with me on this one. You may find the extracts from the MS knowledge base useful if anyone else has the same kind of problem. (Incidentally I couldn't get GetObject / CreateObject to compile on my version of Visual Studio - even when I switched all the options and error messaging off, otherwise I might well have gone down this less stressful, but less perfect, route.)
0
 
LVL 9

Expert Comment

by:Hawkvalley1
ID: 26212020
Good to see you got working, I have not come across that specific problem or able reproduce it, but it is a good learning experience for all. Thanks for posting the KB articles.
0
 

Author Comment

by:JeremyHigginson
ID: 26212132
Thank you for your suggestions. It also worked on my remote tester's PC, which was the acid test. Overall, though, I would consider it to be a flaw in Microsoft's coding somewhere. Also I think it would be much more sensible if you could simply piggyback on an existing Word instance if there is one; then when a user closes Word, every one of the open files will be closed in turn, rather than leaving some behind that have to be closed by switching to the second instance - which is a bit messy.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Screencast - Getting to Know the Pipeline
The Relationships Diagram is a good way to get an overall view of what a database is keeping track of. It is also where relationships are defined. A relationship specifies how two tables connect to each other. As you build tables in Microsoft Ac…
Suggested Courses

571 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