How can I close file created by Word SaveAs2 method?

I am running Visual Studio 2015 Community, visual basic. I am referencing Microsoft.Office.Interop.Word. The code below creates a PDF file by converting a simple Word file using the Doc.SaveAs2 method with the PDF parameter for the format. My problem is that when I try to delete the PDF file later in the application, it tells me that it is still in use. It seems like all I should need to do would be to close the file, but I'm not sure how to do that. The code below closes the Word document but not the PDF. I've tried using the FileClose() method but it only accepts an integer as a parameter. I've tried it with no value, a 1 and a 2, but I'm still getting the "file in use" error when I try to delete it. I'm very new to VB coding and would appreciate any help.


Private Sub CreateTitlePage()

        Dim wdApp As Microsoft.Office.Interop.Word.Application = New Microsoft.Office.Interop.Word.Application
        Dim wdDoc As Microsoft.Office.Interop.Word.Document = New Microsoft.Office.Interop.Word.Document
        Dim wdPara1 As Microsoft.Office.Interop.Word.Paragraph
        'Dim wdPage1 As Microsoft.Office.Interop.Word.Page

        wdDoc.Application.Visible = False
        wdDoc.PageSetup.VerticalAlignment = WdVerticalAlignment.wdAlignVerticalCenter

        wdPara1 = wdDoc.Content.Paragraphs.Add
        wdPara1.Range.InsertParagraphAfter()
        wdPara1.Range.Text = "BINDER DOCUMENT" + vbVerticalTab + vbVerticalTab + "Created on:  " + formattedDate2
        wdPara1.Range.Font.Bold = True
        wdPara1.Range.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter

        ' The following statements save the document and close the Word application
        wdDoc.SaveAs(binderNameDoc)
        wdDoc.Close()
        wdApp.Quit()

        ConvertWordToPDF(tbProject.Text + "\", "Binder" + formattedDate, docLit)

    End Sub



    Public Sub ConvertWordToPDF(myPathName As String, myFileName As String, myFileExt As String)

        Dim myWordName As String = myPathName + myFileName + myFileExt
        Dim myPDFName As String = myPathName + myFileName + pdfLit
        Dim word As Microsoft.Office.Interop.Word.Application = New Microsoft.Office.Interop.Word.Application()
        Dim doc As Microsoft.Office.Interop.Word.Document = word.Documents.Open(myWordName)
        Dim doc2 As PdfDocument = New PdfDocument
        doc.Activate()
        doc.SaveAs2(myPDFName, WdSaveFormat.wdFormatPDF)
        doc.Close()

        ReDim Preserve pdfArray(pdfArray.Length)
        pdfArray(countConversions) = myPDFName
        countConversions = countConversions + 1

End Sub

Open in new window

johnrosshAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jacques Bourgeois (James Burger)PresidentCommented:
Close and Quit do not always do the job with Office applications when you run them from VB.NET, because .NET and COM (Word is a COM application) do not handle memory the same way.

When you have problems such as these, usually calling ReleaseComObject after calling Close or Quit will release the object that stuck in memory.

And you seem to have an unused doc2 variable in your ConvertToWordPDF method.
0
johnrosshAuthor Commented:
Thanks Jacques. I tried putting in the code below to call the ReleaseComObject function, but I get a compile time error saying that function isn't available. Is there a reference that I need to include to have that available?

releaseStatus = ReleaseComObject(wdDoc)
0
Jacques Bourgeois (James Burger)PresidentCommented:
No need for a reference, it is included in mscorlib.dll, the .NET runtime, that is always referenced in any type of .NET application.

But you need to specify the class name:

releaseStatus = Marshal.ReleaseComObject(wdDoc)
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

johnrosshAuthor Commented:
Sorry Jacques, I had already tried that. I get a compile time error saying "Marshal is not declared".
0
Jacques Bourgeois (James Burger)PresidentCommented:
Then, let's go further, it's because the namespace is not imported. So, you either add the following at the top of the code file:

     Imports System.Runtime.InteropServices

or you specify the namespace when calling the method:

     System.Runtime.InteropServices.Marshal.ReleaseComObject(wdDoc)
0
johnrosshAuthor Commented:
Thanks Jacques. Sorry to be a little slow on the uptake here. I added the import statement and got rid of the error but it didn't have any effect on the final result. I'm still getting an error saying that it can't delete the file because it's in use. I tried using Marshal.FinalReleaseComObject as well but there was no difference.
0
Jacques Bourgeois (James Burger)PresidentCommented:
Don't be sorry. It only shows that you are beginning in .NET, so you still have to get the way things are going.

In .NET, a method is never called alone. It's always done through an object (variable) or a class in the case of Shared methods such as ReleaseComObject.

If you still encounter methods that you call directly, they are either methods you created yourself in a module or old Visual Basic methods that have been kept only to help programmers make the transition from VB6. There is always a better way to do it in pure .NET methods, but you need to find the class in which the method is defined.

If you try to call a method and it does not work, this is because you did not specify the namespace for the class. Consider a namespace as a kind of directory in which to look for classes. Just as you need to specify the path to use a file, you need to define the namespace to use a class. This can be done directly on the call itself, or through an Import, which tells the compiler to consider that namespace as a default for the file in which you use it.

If it still does not work with the namespace, then you are missing the reference to the dll.

If you look at any page in the documentation for a class, method or property, these informations are given right at the top of the page. That shows how important these are when working in .NET.

Back to your problem.

First, note that you do not always have to go through all that trouble. In many situations, you just manipulate the Office application as you would have done in VBA. Some programmers use ReleaseComObject all the time, but usually, you might wait until you have these kind of problems before you do so.

Are you using ReleaseComObject on all the objects: Document and Application? If you release the Document and the Application is not released afterward, the Application might hold a reference to the Document. You can verify that the Application is released properly by going in the Task Manager (Ctrl-Alt-Delete) and look for Microsoft Word in the processes. If it is still there, then Word is still running in the background, things were not released properly.

In some situations, you also need to release the objects that you created inside of Word, such as your Paragraph, and eventually the Page that you commented out.

But this can be tricky. The release should be done in the reverse order of the object hierarchy. Because the Application contains the Document, the Document contains the Paragraph, you have to release the Paragraph first, then the Document, then the Application.
0
johnrosshAuthor Commented:
Thanks for your comments Jacques. I think I have things set up the way you suggest but I'm still getting the error when I try to delete the file. This is what the code looks like now. Do you see anything I'm doing incorrectly?

    Private Sub CreateTitlePage()

        Dim wdApp As Microsoft.Office.Interop.Word.Application = New Microsoft.Office.Interop.Word.Application
        Dim wdDoc As Microsoft.Office.Interop.Word.Document = New Microsoft.Office.Interop.Word.Document
        Dim wdPara1 As Microsoft.Office.Interop.Word.Paragraph

        wdDoc.Application.Visible = False
        wdDoc.PageSetup.VerticalAlignment = WdVerticalAlignment.wdAlignVerticalCenter

        wdPara1 = wdDoc.Content.Paragraphs.Add
        wdPara1.Range.InsertParagraphAfter()
        wdPara1.Range.Text = "BINDER DOCUMENT" + vbVerticalTab + vbVerticalTab + "Created on:  " + formattedDate2
        wdPara1.Range.Font.Bold = True
        wdPara1.Range.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter

        ' The following statements save the document and close the Word application
        wdDoc.SaveAs(binderNameDoc)
        wdDoc.Close()
        wdApp.Quit()

        ConvertWordToPDF(tbProject.Text + "\", "Binder" + formattedDate, docLit)

        releaseStatus = Marshal.FinalReleaseComObject(wdPara1)
        releaseStatus = Marshal.FinalReleaseComObject(wdDoc)
        releaseStatus = Marshal.FinalReleaseComObject(wdApp)

    End Sub


    Public Sub ConvertWordToPDF(myPathName As String, myFileName As String, myFileExt As String)

        Dim myWordName As String = myPathName + myFileName + myFileExt
        Dim myPDFName As String = myPathName + myFileName + pdfLit
        Dim word As Microsoft.Office.Interop.Word.Application = New Microsoft.Office.Interop.Word.Application()
        Dim doc As Microsoft.Office.Interop.Word.Document = word.Documents.Open(myWordName)
        doc.Activate()
        doc.SaveAs2(myPDFName, WdSaveFormat.wdFormatPDF)
        doc.Close()
        word.Quit()

        releaseStatus = Marshal.FinalReleaseComObject(doc)
        releaseStatus = Marshal.FinalReleaseComObject(word)

        ReDim Preserve pdfArray(pdfArray.Length)
        pdfArray(countConversions) = myPDFName
        countConversions = countConversions + 1

    End Sub
0
Jacques Bourgeois (James Burger)PresidentCommented:
Unfortunately, it looks OK to me, so the problem might be somewhere else.

But have you checked the value of releaseStatus to make sure that the release was successful? It should normally be 0?

Have you checked that Word is not still running as a process in the background? If not, then it means that everything closed down normally, so something else than your code is holding the file somehow.

One thing I might try to is to display the Application and Document on the screen, by setting their Visible property to True. You can sometime pinpoints problems that are not evident from the code. I have seen some warning messages that do not show when Word runs invisible, but do show when there is a user interface.
1

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
DrTribosCommented:
@JohnRossh hi I was wondering if you would mind sharing your solution - learning C# and was watching with interest.

Thanks in advance,
0
johnrosshAuthor Commented:
Hi Dr Tribos, I found that once I had the FinalReleaseComObject statements in the right order, it worked. I had to prove that to myself by trying to delete the files immediately after they had been created. It worked. Then I found I was getting the same error but it was caused by a function that merged an array of PDF files. I found a more efficient way to do the merge and it worked perfectly.
1
DrTribosCommented:
Thanks for following up so quickly, much appreciated!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.