'The RPC server is unavailable.' 循环遍历 word 文档时

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

我正在开发一个在 Word 中查找和更新 DOC 变量的实用程序。我有一段代码可以遍历文档并显示一个带有变量名的消息框,但是当它试图打开下一个文档时我收到了一个错误。错误是:

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

我很困惑,因为我的代码不访问任何网络。我认为可能发生的情况是文档关闭时 Word 正在关闭,但我找不到防止这种情况发生的解决方案。

我尝试过的其他事情:

  1. 已确认 UAC 已禁用
  2. 确认的 RPC 服务是 运行
  3. 已确认 RPC 和 DCOM 的注册表值正确

    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
    
'Loop through .docx files replacing variables
Private Sub LoopTemp()
    Dim oDir As New DirectoryInfo(dPath)
    Dim oFileArr As FileInfo() = oDir.GetFiles()
    Dim oFile As FileInfo
    Dim oVar As Variable
    Dim oWord As Application

    For Each oFile In oFileArr

        oWord = CreateObject("Word.Application")
        oWord.Visible = False

        GC.Collect()
        GC.WaitForPendingFinalizers()

        Dim oDoc = New Document()
        oDoc = oWord.Documents.Open(oFile.FullName)

        For Each oVar In oDoc.Variables
            MsgBox(oVar.Name)
        Next

        oDoc.Close(SaveChanges:=WdSaveOptions.wdSaveChanges)
        Marshal.FinalReleaseComObject(oDoc)

        oWord.Quit()
        Marshal.FinalReleaseComObject(oWord)

    Next

End Sub

当我将 oWord 移入循环时,更新的代码起作用了。现在它创建一个新对象并为每个文档退出。不知道有没有更好的方法。

当 COM 对象的 "pointer" 在代码尝试 re-use 之前未从内存中正确释放时,会出现 RPC 错误。当从应用程序本身外部自动化 Office 应用程序时,这是一个非常常见的问题。尤其是在使用 .NET 时,必须格外小心。

另一个需要注意的非常重要的事情是 New 关键字绝不能与任何 Office 对象一起使用 除了 Application。尽管 API 允许,但切勿在 Word 中使用 New Document,因为这会创建无法正确释放的 Document 对象。

出于效率原因,启动 Word 应用程序一次 应该就足够了 - 没有必要在循环中重复,只要它使用的 COM 对象被正确释放(设置为 Nothing 并收集垃圾)。

我会把题中的代码写成这样:

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