首页 > 解决方案 > 'RPC 服务器不可用。循环浏览word文档时

问题描述

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

System.Runtime.InteropServices.COMException: 'RPC 服务器不可用。(来自 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
    

标签: vb.netms-wordoffice-interop

解决方案


当一个指向 COM 对象的“指针”在代码尝试重用它之前没有从内存中正确释放时,就会出现 RPC 错误。当从应用程序本身自动化 Office 应用程序时,这是一个很常见的问题。尤其是在使用 .NET 工作时,必须非常小心。

另一个需要注意的非常重要的事情是,New关键字不应该与任何 Office 对象一起使用,除了 Application. 尽管 API 允许这样做,但切勿New Document与 Word 一起使用,因为这会创建一个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

推荐阅读