Office Interop在Windows服务中不起作用

时间:2012-11-20 17:55:05

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

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

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

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

但是,如果我从WPF或Windows Form应用程序中使用该库,我从未遇到任何问题。我知道线程存在问题,(单线程公寓)但是我不知道如何修复它以解决Windows服务问题。 :( :( :(

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

异常消息:{“对象引用未设置为对象的实例。”}(参考word文档)。内在例外:无效; HResult:-2147467261。数据:ListDictionaryInternal有0个条目;堆栈跟踪:位于c:\ Project Files ... \ DocumentConverter.cs:第209行的DocumentConverter.ToPdf(String currentWorkingFolderPath,String pathToDocumentToConvert)

所以这是库函数。它需要Microsoft Office引用,该引用由Visual Studio Tools for 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;
}

5 个答案:

答案 0 :(得分:23)

Per @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系统包含了systemmprofile下的桌面文件夹,该文件夹于2008年缺席。

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

下创建

C:\的Windows \ system32 \设置\ systemprofile

C:\的Windows \ Syswow64资料\配置\ systemprofile

谢谢大家......!

答案 1 :(得分:4)

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

您需要使用一些库来实现您的目标:

答案 2 :(得分:3)

创建这些文件夹后:

  

C:\的Windows \ system32 \设置\ systemprofile \桌面   C:\的Windows \ Syswow64资料\配置\ systemprofile \桌面

确保计划任务正在运行时,个人资料可以访问这些文件夹。

答案 3 :(得分:1)

您的Windows服务是否启用了“以交互模式运行”选项?它可能会失败,因为Word正在尝试显示一个用户界面,出于看似显而易见的原因,它无法做到。

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

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

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

答案 4 :(得分:0)

按照以下链接中的说明,我的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