c# - Microsoft Interop Word Automation的DCOM配置设置

标签 c# .net office-interop com-interop dcom

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



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

即使我先将计算机加入域,然后以域用户身份登录然后安装Microsoft Office,Local Path还是会先正确显示,然后在重新启动后再次变为空白。同时,如果我使用Local User登录,则Path仍然存在。

是什么导致Local Path的值变为空白?

所有这些设置都在虚拟机上执行,而自动化一词在域帐户上运行,因为我看到它在加入域的物理机上运行。

UPDATE: What my application is doing:


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

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

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

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


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



使用Word Interop将生成的WordML保存为Word格式文件之一。
将生成的WordML导出到PDF文件。
将多个WordML合并为一个Word文档文件。
为此获取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而不是尝试解决该错误,然后尝试另一种解决问题的方法:

(...)Microsoft当前不建议并且不支持从任何无人参与的非交互客户端应用程序或组件(包括ASP,DCOM和NT Services)自动化Microsoft Office应用程序,因为Office可能表现出不稳定的行为和/或在此环境中运行时死锁。 (...)

该知识库中建议的一些替代方法是:

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

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



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


Open XML SDK Documentation
How to: Manipulate Office Open XML Formats Documents
Manipulating Word 2007 Files with the Open XML Object Model (Part 1 of 3)
Manipulating Word 2007 Files with the Open XML Object Model (Part 2 of 3)
Manipulating Word 2007 Files with the Open XML Object Model (Part 3 of 3)(...)


请注意,即使您解决了问题,您的解决方案也将很难稳定……本质上,似乎正在发生的事情是您弄乱了注册表,似乎您的Word重新安装并没有解决您的注册表问题,并且有问题。

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

更新1

您有一个Hello World示例here
使用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(); 
  } 
}


注意

我可能会花几个小时来尝试解决您的注册表,但是正如您在我的博客中的this article中所看到的那样,这些问题令人头疼,即使您找到解决问题的方法,也不会我认为当然是一种可维护或可扩展的解决方案。

更新2

根据this,这些配置(例如本地路径)是从注册表中提取的,不可修改:

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

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

所以!运行> regedit>转到HKEY_CLASSES_ROOT \ CLSID,然后转到“编辑”菜单,然后单击“查找”,按键过滤并将您的ApplicationID放在此处。您应该以这种方式找到它。

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

如果可行,请在每次登录后测试该值是否重新启动并使用您的域用户帐户登录后是否保持有效,如果不是,请运行批处理来运行.reg文件以执行此修改。

警告:不过,这是不好的东西,我强烈,强烈建议您采取相反的态度,这不是做到这一点的方法。

更新3

关于“ MS-WORD AUTOMATION ERROR:“消息过滤器指示应用程序正忙”,您对这个问题here有很好的答复。我将在上面的链接中引用一些内容,以进一步了解原因该错误发生:

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

关于合并,该tool声称能够合并OpenXML文档,但我从未使用过,但是我会尝试一下(如果您是我的话)。

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

最后,要从Word文档生成PDF,可以使用此工具here

因此,正如您所看到的,您可以继续使用Word Automation(暗面),或者可以加入Force的浅面:)。

关于c# - Microsoft Interop Word Automation的DCOM配置设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23707475/

相关文章:

.NET 游戏服务器

c# - 将缓存项转换为特定对象类型以供 web 方法返回

c# - ServiceStack 中的直通身份验证

c# - 有什么办法可以绕过 private 关键字吗?

vb.net - 执行 Action 时检测随机的Powerpoint卡住

c# - 如何克服自定义文档属性大小限制

c# - 如何为 Outlook AppointmentItem 的类别着色

C#寻找相似的颜色

c# - XSP4 本地主机不响应 (Windows 8.1)

c# - "DataReader already open"有问题