Microsoft Interop Word Automation 的 DCOM 配置设置

2024-01-05

我在用Microsoft Office Interop Word使用 C# 生成文档。为了使文档生成正常工作,应该有一个条目"Microsoft Office Word 97 - 2003 Document"在下面Dcom Config Settings如下所示:

The Local Path在下面General Tab首次安装 Microsoft Office 时具有正确的路径。如果我随后将计算机加入域,然后使用域用户重新启动系统,Local Path变为空白,应用程序不会生成文档并给出错误。

即使我先将计算机加入域,然后使用域用户登录,然后安装 Microsoft Office,Local Path首先显示正确,然后重新启动后,它又变成空白。同时,如果我使用Local User, the Path仍然在那里。

是什么造成了价值Local Path变成空白?

所有设置都在虚拟机上进行,并且“自动化”一词在域帐户上工作,就像我看到它在加入域的物理机上工作一样。

UPDATE: What my application is doing:

我的应用程序中有 4-5 个组件。

第一个是 VSTO Word AddIn,它与 Microsoft Word 集成,我们在其中创建包含一些也保存在数据库中的表达式的新文档。表达式也有条件,它们也可以嵌套。表达式包含来自保存在数据库中的 XSD 文件的架构元素。创建此类文档后,其 WordML 将保存在数据库中。这一切都是在 VSTO AddIn 中完成的。

第二个是一个 Web 服务,它从另一个组件接收输入 xml,该组件与上面的 XSD 进行确认,其中架构元素已嵌入到通过 VSTO addIn 创建的文档中的表达式中。该 Web 服务检查验证和其他几个任务。然后,它从数据库获取相应 Word 文档的 WordML,并将其传递给 Word Interop,Word Interop 使用其 API 递归地迭代它,以将架构元素替换为输入 xml 中的实际值。然后将 WordML 作为 Word 文档保存到文件中。

这还会在保存文档之前将模板附加到文档。它还使用 Word Interop 的 SaveAs 功能将文件另存为 PDF。

更新: 我再次浏览了完整的应用程序,并了解到我们正在通过解析 Office Open XML 来完成所有操作(例如,将输入提供给 Word 文档),但我们使用 Word Automation 所做的唯一事情如下:

  1. 使用 Word Interop 将生成的 WordML 保存为 Word 格式文件之一。
  2. 将生成的 WordML 导出到 PDF 文件。
  3. 将多个 WordML 合并到一个 Word 文档文件中。
  4. 为其获取 XML。

所有这四个代码如下所示,仅包含相关部分的代码:

Microsoft.Office.Interop.Word.Document wordDocument = null;
object templateName = "templateFile.dotm";
wordDocument = this.WordApplication.Documents.Add(ref missing, ref missing, ref missing, ref missing);
wordDocument.Range(ref missing, ref missing).Text = "";
wordDocument.set_AttachedTemplate(ref templateName);

wordDocument = this.WordApplication.Documents.Open(
                   ref objSourceFilePath, ref oFalse, ref oTrue,
                   ref oMissing, ref oMissing, ref oMissing,
                   ref oMissing, ref oMissing, ref oMissing,
                   ref oMissing, ref oMissing, ref oMissing,
                   ref oMissing, ref oMissing, ref oMissing,
                   ref oMissing);
wordDocument.ExportAsFixedFormat(
        strTargetPath,
        targetFormat,
        paramOpenAfterExport,
        paramExportOptimizeFor,
        paramExportRange,
        paramStartPage,
        paramEndPage,
        paramExportItem,
        paramIncludeDocProps,
        paramKeepIRM,
        paramCreateBookmarks,
        paramDocStructureTags,
        paramBitmapMissingFonts,
        paramUseISO19005_1,
        ref oMissing);

object SaveToFormat = SaveToFormat = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatDocument97;
wordDocument.SaveAs(ref objTargetFilePath, ref SaveToFormat, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);

对于合并多个文件:

Microsoft.Office.Interop.Word.Document doc = null;
Microsoft.Office.Interop.Word.Section section = null;
object sectionBreakNextPage = (object)WdBreakType.wdSectionBreakNextPage;

WordApp.Visible = false;
doc = this.WordApplication.Documents.Add(ref paramMissing, ref paramMissing, ref paramMissing, ref paramMissing);

if (doc != null)
{
    doc.Activate();
    int fileCount = sourceFiles.Length;
    String fileName = string.Empty;

    for (int fileIndex = 0; fileIndex < fileCount; fileIndex++)
    {
        fileName = sourceFiles[fileIndex];
        if (System.IO.File.Exists(fileName))
        {
            section = doc.Sections.Last;
            //delink the current section's header & footer from previous section's header & footer
            section.Headers[WdHeaderFooterIndex.wdHeaderFooterFirstPage].LinkToPrevious = false;
            section.Footers[WdHeaderFooterIndex.wdHeaderFooterFirstPage].LinkToPrevious = false;
            section.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary].LinkToPrevious = false;
            section.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary].LinkToPrevious = false;
            section.Headers[WdHeaderFooterIndex.wdHeaderFooterEvenPages].LinkToPrevious = false;
            section.Footers[WdHeaderFooterIndex.wdHeaderFooterEvenPages].LinkToPrevious = false;

            section.Range.InsertFile(fileName, ref paramMissing, ref paramMissing, ref paramMissing, ref paramMissing);
            //if it is last iteration, do'nt insert break
            if (fileIndex < fileCount - 1)
            {
                object rangeStart = (object)(section.Range.End - 1);
                doc.Range(ref rangeStart, ref paramMissing).InsertBreak(ref sectionBreakNextPage);
            }
        }
    }
    doc.SaveAs(ref targetFile, ref wordFormat, ref paramMissing,
        ref paramMissing, ref paramMissing, ref paramMissing,
        ref paramMissing, ref paramMissing, ref paramMissing,
        ref paramMissing, ref paramMissing, ref paramMissing,
        ref paramMissing, ref paramMissing, ref paramMissing,
        ref paramMissing);
    return true;
}

现在,我收到以下错误:

The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))

这一切可以在不使用 Word Automation 的情况下完成吗?


我认为您应该阅读,而不是尝试修复和处理该错误this http://support.microsoft.com/kb/257757/en-us然后尝试另一种方法来解决您的问题:

(...)Microsoft 目前不建议也不支持从任何无人值守、非交互式客户端应用程序或组件(包括 ASP、DCOM 和 NT 服务)实现 Microsoft Office 应用程序的自动化,因为 Office 在运行时可能会表现出不稳定的行为和/或死锁在这种环境下。(...)

该知识库中推荐的一些替代方案是:

(...)Microsoft 强烈推荐多种替代方案,这些方案不需要在服务器端安装 Office,并且可以比自动化更高效、更快速地执行大多数常见任务。在将 Office 作为项目中的服务器端组件使用之前,请考虑替代方案。

大多数服务器端自动化任务涉及文档创建或编辑。 Office 2007 支持新的 Open XML 文件格式,使开发人员可以在服务器端创建、编辑、读取和转换文件内容。这些文件格式使用 Microsoft .NET 3.x Framework 中的 System.IO.Package.IO 命名空间来编辑 Office 文件,而无需使用 Office 客户端应用程序本身。这是处理服务中 Office 文件更改的推荐和支持的方法。(...)

And

(...)Microsoft 提供了一个 SDK,用于操作 .NET 3.x Framework 中的 Open XML 文件格式。有关 SDK 以及如何使用 SDK 创建或编辑 Open XML 文件的详细信息,请访问以下 Microsoft Developer Network (MSDN) 网站:

  • 开放 XML SDK 文档 http://msdn.microsoft.com/en-us/library/bb226703.aspx
  • 如何:操作 Office Open XML 格式文档 http://msdn.microsoft.com/en-us/library/aa982683.aspx
  • 使用 Open XML 对象模型操作 Word 2007 文件(第 1 部分,共 3 部分) http://msdn.microsoft.com/en-us/library/bb656295.aspx
  • 使用 Open XML 对象模型操作 Word 2007 文件(第 2 部分,共 3 部分) http://msdn.microsoft.com/en-us/library/bb739835.aspx
  • 使用 Open XML 对象模型操作 Word 2007 文件(第 3 部分,共 3 部分) http://msdn.microsoft.com/en-us/library/bb727374.aspx (...)

请注意,即使您解决了问题,您的解决方案也很难稳定...从本质上讲,似乎发生的情况是您弄乱了注册表,并且似乎您的 Word 重新安装并没有修复您的注册表,并且是有问题的。

基于此,我建议您阅读上述文档,并尝试使用上述替代方案组合出一个更稳定的解决方案,因为来自任何无人值守、非交互式客户端应用程序或组件(您的情况)的 Microsoft Office 应用程序自动化可能会表现出不稳定的行为。

UPDATE 1

您有一个 Hello World 示例here http://msdn.microsoft.com/en-us/library/dd440953%28v=office.12%29.aspx。 使用 Open XML 创建文档就像执行以下操作一样简单:

public void HelloWorld(string docName) 
{
  // Create a Wordprocessing document. 
  using (WordprocessingDocument package = WordprocessingDocument.Create(docName, WordprocessingDocumentType.Document)) 
  {
    // Add a new main document part. 
    package.AddMainDocumentPart(); 

    // Create the Document DOM. 
    package.MainDocumentPart.Document = 
      new Document( 
        new Body( 
          new Paragraph( 
            new Run( 
              new Text("Hello World!"))))); 

    // Save changes to the main document part. 
    package.MainDocumentPart.Document.Save(); 
  } 
}

Note

我可以在这里花几个小时,试图解决你的注册表问题,但正如你所看到的本文 http://pinho.icodebox.net/2014/02/fixing-windows-registry-broken.html在我的博客中,这些问题是非常令人头疼的,就你的情况而言,即使你找到解决它的方法,它也不会是一个可维护或可扩展的解决方案,当然,在我看来。

UPDATE 2

根据this http://support.microsoft.com/kb/182248,本地路径等配置是从注册表中提取的,不可修改:

(...)常规选项卡提供有关应用程序的常规信息。此选项卡显示应用程序名称、类型(本地服务器或远程服务器)和位置(本地路径或远程计算机)。这些设置无法通过 DCOM 配置界面进行修改。

常规选项卡从以下注册表项的子项中检索其所有信息: HKEY_CLASSES_ROOT\CLSID{...CLSID...} 其中 {...CLSID...} 是当前正在查看的对象服务器的唯一 CLSID。(...)

所以!运行 > regedit > 转到 HKEY_CLASSES_ROOT\CLSID,然后转到编辑菜单并单击查找,按键过滤并将您的 ApplicationID 放在那里。你应该这样找到它。

现在找到 DCOM 的注册表项后,将其展开,您应该会看到 LocalServer32,属性(默认)保存您的本地路径值,尝试将其更改为与新的 Oracle Virtual Box 中相同的路径。

如果有效,请测试重新启动并使用域用户帐户登录后该值是否保持不变,如果保持不变,那就太好了;如果没有,请在每次登录时运行批处理以运行 .reg 文件来执行此修改。

Warning:然而,这是不好的事情,我强烈强烈鼓励你反其道而行之,这不是这样做的方法。

UPDATE 3

关于“MS-WORD 自动化错误:“消息过滤器表明应用程序正忙”,您对该问题有很好的答复here http://social.msdn.microsoft.com/Forums/vstudio/en-US/70ef972b-51b6-4ece-a4af-d6b4e111eea5/msword-automation-error-the-message-filter-indicated-that-the-application-is-busy?forum=vsto。我将引用上面链接的一些内容,以进一步理解为什么会发生该错误:

(...)该问题是您调用的 Word 对象不支持多线程。由于它们通过 COM 暴露给任意客户端,因此存在多个线程可能尝试同时执行对象内的代码的可能性。为了防止这种情况发生,将通过将所有传入调用排队并一次只允许执行一个调用来序列化它们。这是通过打包每个呼叫的详细信息并将消息发布到 Word 来完成的。当Word处理消息时,调用将在Word自己的主线程上执行。这种方法的问题在于,如果来电时 Word 正忙于执行其他操作,则呼叫者将不得不等待。(...)

关于合并,这tool http://powertools.codeplex.com声称能够合并 OpenXML 文档,我从未使用过它,但我会尝试一下(如果我是你)。

(...)PowerTools for Open XML 包含使用 Open XML SDK 完成各种常见任务的源代码和指南,例如: - 使用 HtmlConverter.cs 将 DOCX 高保真转换为 HTML/CSS; - 使用 DocumentBuilder.cs 合并和拆分 DOCX 文档; - 使用PresentationBuilder.cs合并和分割PPTX演示文稿; - 使用 RevisionAccepter.cs 接受 DOCX 文档中跟踪的修订; - 使用 TextReplacer.cs 搜索和替换 DOCX 文档中的文本(...)

最后,要从 Word 文档生成 PDF,您可以使用此工具here http://sourceforge.net/projects/itextsharp/.

因此,正如您所看到的,您可以再次继续处理 Word Automation(黑暗面),也可以加入原力的光明面:)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Microsoft Interop Word Automation 的 DCOM 配置设置 的相关文章

  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • 枚举扩展方法

    在vs2008中 是否可以编写适用于任何枚举的扩展方法 我知道您可以针对特定枚举编写扩展方法 但我希望能够使用单个扩展方法对每个枚举进行处理 这可能吗 是的 只需针对基础进行编码Enum类型 例如 public static void So
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐