5

我对 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;
}
4

5 回答 5

26

根据@Sameer S 在他的帖子中:Windows server 2008 是否支持 Office 2003 互操作 ..?

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

多谢你们..!

于 2012-11-21T16:23:08.763 回答
6

创建这些文件夹后:

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

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

于 2016-10-05T11:28:24.447 回答
4

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

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

于 2012-11-20T19:04:04.037 回答
1

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

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

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

编辑:我浏览了 MSDN 文档(用于 Word Interop),似乎不需要使用 VSTO。您可以尝试使用纯单词互操作来执行此操作并查看它是否有效吗?这篇文章有一个例子

于 2012-11-20T17:59:35.757 回答
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
于 2013-04-25T07:58:01.713 回答