【问题标题】:Office Interop Does Not Work in Windows ServiceOffice 互操作在 Windows 服务中不起作用
【发布时间】:2012-11-20 17:55:05
【问题描述】:

我对 Microsoft Office 有一个非常奇怪的问题。

我有一个公共库,其唯一目的是打开任何传递给它的 word 文档文件类型(通过完整的文件路径...)并将打开的 word 文档另存为 pdf 文件。

奇怪的问题是,如果我从 Windows 服务中使用该库,每当它尝试打开 word 文档时,我都会得到一个空值……也就是说,word 文档永远不会被打开。

但是,如果我使用 WPF 或 Windows 窗体应用程序中的库,我就不会遇到任何问题。我知道线程存在问题,(单线程公寓)但是我不知道如何修复它以摆脱 Windows 服务。 :( :( :(

如果有任何帮助,我将不胜感激!我得到的错误如下:

异常消息:{“对象引用未设置为对象的实例。”}(指的是 word 文档)。内部异常:空; H结果:-2147467261。数据:ListDictionaryInternal,有 0 个条目;堆栈跟踪:在 c:\Project Files...\DocumentConverter.cs:line 209 中的 DocumentConverter.ToPdf(String currentWorkingFolderPath, String pathToDocumentToConvert) 处

所以这里是库函数。它需要由 Visual Studio Tools for Office 创建的 Microsoft Office 参考。

private string ToPDF(string currentWorkingFolderPath, string pathToDocumentToConvert)
{
    string temporaryPdfFolderPath = Path.GetFullPath(currentWorkingFolderPath + "\\pdf\\");
    string temporaryPdfFilePath = Path.GetFullPath(temporaryPdfFolderPath + "\\pdffile.pdf");

    if (!FileSystem.CreateDirectory(temporaryPdfFolderPath))
    {
        return null;
    }

    try
    {
        Microsoft.Office.Interop.Word.Application wordApplication = new Microsoft.Office.Interop.Word.Application();

        object objectMissing = System.Reflection.Missing.Value;

        wordApplication.Visible = false;
        wordApplication.ScreenUpdating = false;

        FileInfo wordFile = new FileInfo(pathToDocumentToConvert);

        Object fileName = (Object)wordFile.FullName;

        // This is where it breaks when called from windows service. Use the dummy value as a placeholder for optional arguments
        Document wordDocument = wordApplication.Documents.Open(ref fileName, ref objectMissing,            
            true, ref objectMissing, ref objectMissing, ref objectMissing, ref objectMissing,            
            ref objectMissing, ref objectMissing, ref objectMissing, ref objectMissing, ref objectMissing,            
            ref objectMissing, ref objectMissing, ref objectMissing, ref objectMissing);



        object outputFileName = (object)temporaryPdfFilePath;
        object fileFormat = WdSaveFormat.wdFormatPDF ;

        // Save document into PDF Format
        wordDocument.SaveAs(ref outputFileName,
            ref fileFormat, ref objectMissing, ref objectMissing,
            ref objectMissing, ref objectMissing, ref objectMissing, ref objectMissing,
            ref objectMissing, ref objectMissing, ref objectMissing, ref objectMissing,
            ref objectMissing, ref objectMissing, ref objectMissing, ref objectMissing);

        // Close the Word document, but leave the Word application open.
        // doc has to be cast to type _Document so that it will find the
        // correct Close method.                
        object saveChanges = WdSaveOptions.wdDoNotSaveChanges;
        ((_Document)wordDocument).Close(ref saveChanges, ref objectMissing, ref objectMissing);

        wordDocument = null;

        // word has to be cast to type _Application so that it will find
        // the correct Quit method.
        ((Microsoft.Office.Interop.Word._Application)wordApplication).Quit(ref objectMissing, ref objectMissing, ref objectMissing);

        wordApplication = null;

    }
    catch (Exception ex)
    {
        //logging code
        return null;
    }

    return temporaryPdfFilePath;
}

【问题讨论】:

  • 这个问题的答案可以在以下线程中找到:stackoverflow.com/questions/4438121/…
  • 这不是真正的“答案”,但基本上是您服务器的安全漏洞:-(
  • 从 ASP.NET 或其他服务器技术使用 Office 互操作是一个可怕的想法。这些 API 是为在桌面应用程序中使用而编写的,用于自动化 Office(一套桌面应用程序)。服务器应用程序在许多方面都不同,这使得在其中使用 Office Interop 是一个非常非常糟糕的主意。它也不受 Microsoft 支持,并且可能违反您的 Office 许可证。见Considerations for server-side Automation of Office

标签: c#-4.0 windows-services vsto office-interop


【解决方案1】:

@Sameer S 在他的帖子中:Is Office 2003 interop supported on Windows server 2008 ..?

Microsoft 在 Windows server 2008 上正式不支持 Microsoft Office 2003 Interop。

但是在对代码和搜索进行大量排列和组合之后,我们发现了一种适用于我们场景的解决方案。

解决方法是弥补 Windows 2003 和 2008 维护其文件夹结构的方式之间的差异,因为 Office Interop 依赖于桌面文件夹在中间打开/保存文件。 2003系统的桌面文件夹在systemprofile下,2008没有。

因此,当我们在 2008 年在相应的层次结构下创建此文件夹时,如下所示; office Interop 能够根据需要保存文件。需要在

下创建此桌面文件夹

C:\Windows\System32\config\systemprofile

C:\Windows\SysWOW64\config\systemprofile

谢谢各位..!

【讨论】:

  • 添加那些桌面文件夹对我有用。非常晦涩但有效!当 Windows 服务调用正在启动 word (win 2008r2) 的 COM dll 时,Word 之前挂起。
  • 请注意,到目前为止可能适用于您的情况,但总的来说,不起作用跨度>
  • 数小时寻找解决方案,终于找到你了!!非常感谢你!!它也对我有用。使用 office 2010 和 windows server 2008 上运行的 windows 服务。
  • 这太疯狂了!!!有用。出现错误“文档名称或路径无效”
  • 我在 Server 2012 R2 上使用 Office 2013(我认为是 32 位),这个疯狂的解决方案仍然适用。非常感谢!你拯救了这一天!
【解决方案2】:

创建这些文件夹后:

C:\Windows\System32\config\systemprofile\Desktop C:\Windows\SysWOW64\config\systemprofile\Desktop

确保调度任务正在使用有权访问这些文件夹的配置文件运行。

【讨论】:

  • 这些文件夹在我的服务器上不存在,所以我创建了它们。疯了,这是修复....!!! ?
【解决方案3】:

在类似服务器的场景(如 ASP.NET 或 Windows 服务或类似情况)中,MS不支持Office Interop - 请参阅http://support.microsoft.com/default.aspx?scid=kb;EN-US;q257757#kb2

你需要使用一些库来实现你想要的:

【讨论】:

  • 我已经阅读了 Office 服务器支持手册,这是一个明显的非建设性陈述:“你(又名我......)被搞砸了。”。作为社区的一员,我一直在寻找答案或方向,而不是显而易见的。其他人建议创建一个 windows 应用程序并在服务中创建一个新进程,该进程打开 windows 应用程序进行转换(显然没有 UI。),以便 office 运行时可以正确执行。 @Sameer S 提出了最好的建议,结果证明是解决方案。
  • @bleepzter 我提供了解决问题的方向,并提供了一个链接,其中明确说明不支持您所做的事情(出于技术、安全和许可原因!)...
  • @Yahia +1 - 前几天我回答了一个类似的问题,你不能忽视微软不推荐这样使用 Word Interop。此外,我认为您通过提供替代解决方案做得很好。
  • @bleepzter 您写道:“@Sameer S 提出了最好的建议,结果证明是解决方案。” -> 首先,答案在哪里?如果该答案未在此处发布,请回答您自己的问题并附上原始来源的链接。
  • @bleepzter 记住常见问题解答:“以你希望他们对待你的同样尊重对待他人。我们都在这里一起学习。宽容那些可能不知道你所知道的一切的人. 带上你的幽默感。 - 所以请停止抱怨并开始欣赏人们只是在尽力提供帮助。如果答案不符合“您的公司政策”或其他任何内容,这不是我们的错。
【解决方案4】:

您的 Windows 服务是否启用了“以交互模式运行”选项?它可能会失败,因为 Word 正在尝试显示 UI,但出于显而易见的原因,它不能这样做。

另一种可能性(也是人们遇到的一个非常常见的问题)是您的 Windows 服务在一个无权访问您尝试传递给它的文件/文件夹的帐户下运行。相比之下,WPF/Winforms 程序在用户凭据下运行。

如果这不是问题,是否有任何错误被抛出?检查 Windows 事件日志和/或添加一些日志以查看是否有一些错误被静默抛出。

编辑:我浏览了 MSDN 文档 (for Word Interop),似乎不需要使用 VSTO。您可以尝试使用纯单词互操作来执行此操作并查看它是否有效吗? This post has an example

【讨论】:

  • 开设办公室没有问题。唯一的问题是打开word文档时...作为服务,打开的word文档为空。作为windows窗体...打开的word文档实际上是一个word文档。该服务在完整的管理员帐户下运行。我有日志记录,错误非常难以描述。但是,由于办公室保存了一个为空的 Word 文档,它会被抛出。
  • @bleepzter - “唯一的问题是打开 word 文档时......作为服务,打开的 word 文档为空”——啊,我确实看到你设置了 @987654323 @ 在您的代码中。 “非描述”错误消息实际上说的是什么?您可以将其编辑到您的问题中吗?即使没有帮助,它也会帮助其他通过搜索引擎找到此问题的人
  • 我刚刚添加了异常消息。就像我说的......它确实没有描述性,但是当我附加到服务进程时,它确实会被抛出 WordDocument 的 SaveAs 方法,因为 word 文档为空。 :(
【解决方案5】:

按照以下链接中的说明操作后,我的 ASP.net 2.0 办公自动化应用程序在 Windows 2008 Server 64 位中运行良好。希望对大家有帮助。

http://emalvass.blogspot.com/2010/01/how-to-use-office-2007-automation-in.html

我的示例程序如下:

Imports Microsoft.Office.Interop.Word


Dim Result As Boolean = False

    Dim appWord As New Microsoft.Office.Interop.Word.Application
    Dim wordDocument As Microsoft.Office.Interop.Word.Document

    Try
        Dim oFile As New FileInfo(sPDFFile), sFilePath As String, sFileName As String, sFileNameArr() As String
        Dim sActualFileName As String

        sFileName = oFile.Name
        sFileNameArr = sFileName.Split(".")
        sActualFileName = sFileNameArr(0)
        sFilePath = oFile.DirectoryName & "\" & sActualFileName & ".pdf"

        wordDocument = appWord.Documents.Open(sPDFFile)

        wordDocument.ExportAsFixedFormat(sFilePath, WdExportFormat.wdExportFormatPDF)
        'wordDocument.ExportAsFixedFormat(sFilePath, 17)

        Result = True
        oFile = Nothing

    Catch ex As COMException
        sErrMsg = ex.InnerException.ToString
        Result = False
    Finally
        wordDocument.Close()
        wordDocument = Nothing
        appWord.Application.Quit()
        appWord = Nothing



    End Try


    Return Result

【讨论】:

  • -1:首先,OP 使用的是 Windows 服务,而不是 ASP.NET。其次,Office Interop 不能在任何服务器端应用程序中可靠地工作。
猜你喜欢
  • 1970-01-01
  • 2010-09-19
  • 1970-01-01
  • 2018-05-27
  • 2010-11-05
  • 2011-11-25
  • 2010-11-13
  • 2023-01-26
  • 2020-03-04
相关资源
最近更新 更多