Search code examples
vb.netms-wordoffice-interop

'The RPC server is unavailable.' when looping through word documents


I am working on a utility to find and update DOC VARIABLES in Word. I have a section of code to loop through the documents and present a Message Box with the variable name, but I'm receiving an error when it tries to open the next document. The error is:

System.Runtime.InteropServices.COMException: 'The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

I'm confused because my code does not access any network. I think what might be happening is the Word is closing when the document closes, but I cannot find a solution to prevent that.

Other things I've tried:

  1. Confirmed UAC is Disabled
  2. Confirmed RPC Services are Running
  3. Confirmed Registry Values for RPC and DCOM are correct

    Private Sub LoopTemp()
        Dim oDir As New DirectoryInfo(dPath)
        Dim oFileArr As FileInfo() = oDir.GetFiles()
        Dim oFile As FileInfo
        Dim oVar As Variable
        Dim oDoc = New Document()
    
        Dim oWord As Application
        oWord = CreateObject("Word.Application")
        oWord.Visible = False
    
        For Each oFile In oFileArr
           oDoc = oWord.Documents.Open(oFile.FullName)
    
           For Each oVar In oDoc.Variables
               MsgBox(oVar.Name)
           Next
    
           oDoc.Close(SaveChanges:=WdSaveOptions.wdSaveChanges)
    
        Next
        oWord.Quit()
    End Sub
    

Solution

  • The RPC error appears when a "pointer" to a COM object is not correctly released from memory before code tries to re-use it. This is a common enough problem when automating Office applications from outside the application, itself. Especially when working from .NET great care must be used.

    Another very important thing to note is that the New keyword should never be used with any Office object except Application. Although the APIs allow it, never use New Document with Word as this creates a Document object that can't be correctly released.

    For reasons of efficiency, starting the Word application once should be sufficient - it's not necessary to repeat that within a loop, as long as the COM objects it uses are correctly released (set to Nothing and garbage collected).

    I would write the code in the question as follows:

    Private Sub LoopTemp()
        Dim oDir As New DirectoryInfo(dPath)
        Dim oFileArr As FileInfo() = oDir.GetFiles()
        Dim oFile As FileInfo
        Dim oVar As Variable = Nothing
        Dim oWord As Application = NOthing
        Dim oDoc As Document = Nothing
    
        oWord = New Word.Application
        oWord.Visible = False
    
        For Each oFile In oFileArr
            oDoc = oWord.Documents.Open(oFile.FullName)
            For Each oVar In oDoc.Variables
                MsgBox(oVar.Name)
            Next
            oVar = Nothing
            oDoc.Close(SaveChanges:=WdSaveOptions.wdSaveChanges)
            oDoc = Nothing
    
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            GC.WaitForPendingFinalizers() 
        Next
    
        oWord.Quit()
        oWord = Nothing
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.WaitForPendingFinalizers()
    
    End Sub