服务器上 MS Office 的远程自动化

Remoting Automation of MS Office on the server

我警告你,你的问题对很多人来说似乎很奇怪:) 但我必须 post 因为我的项目经理告诉我存在技术解决方案,即使对我来说不是。

我们有:

我的 PM 想要什么(我告诉他这是不可能的):

这种"remote Ms Office automation is possible"的解决方案对我来说似乎是不可能的。但也许我错了,可以使用 DCOM、WCF 或其他方式吗?

任何人都可以确认我是对的;)

正如您已经从评论中了解到的那样,由于多种原因,使任何 Office 应用程序的桌面版本自动化都是不好的。可以在知识库文章 KB257757 Considerations for server-side Automation of Office 中找到详细信息。该文章的主要内容是:

Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.

但由于您仍然坚持,请将以下示例视为一个非常简单、幼稚、不适合在生产环境附近使用的示例 proof-of-concept,它使您能够快速 运行 解决本文中提到的所有问题知识库文章。

在新的解决方案中创建一个 WCF 服务应用程序和一个控制台应用程序。在 WCF 应用程序中添加以下接口:

[ServiceContract]
public interface IPrintService
{
    [OperationContract]
    string Print(Stream wordDoc);
}

并有一个服务来实现它。确保添加对 Microsoft.Office.Interop.Word 的引用,您可以在“添加引用”对话框的 COM 选项卡中找到它。

public class PrintService : IPrintService
{
    public string Print(Stream wordDocStream)
    {
        // copy our stream to a local file
        var tempFile = Path.GetTempFileName();
        using(var file = File.Create(tempFile))
        {
            wordDocStream.CopyTo(file);
        }

        // start word
        var wordApp = new Microsoft.Office.Interop.Word.Application();
        // setup printer
        wordApp.ActivePrinter = "Canon LBP3010/LBP3018/LBP3050";
        // open, collect data, print and close
        var doc = wordApp.Documents.Open(tempFile);
        doc.PrintOut();
        var res = doc.Words.Count;
        doc.Close(false);

        // quit word
        wordApp.Quit(false);
        // delete temp file
        File.Delete(tempFile);
        return String.Format("{0} words", res);
    }
}

您可以在此处看到一个准系统解决方案,用于打印作为流发送到服务的文档。该服务将流复制到文件、启动 Word、打开文件、打印文档、从文档中获取一些数据并在完成时拆卸和清理。

客户直截了当:

using(var client = new PrintService.PrintServiceClient())
{
    using(var file = File.Open(@"small.docx", FileMode.Open))
    {
        var response = client.Print(file);
        Console.WriteLine(response);
    }
}

从技术上讲,这就是从服务打印 Word 文档所需的全部内容。这 运行s 在开发服务器上没有太多问题。如果你在 IIS 上 运行 这个,你可能必须确保在 AppPool 中用作身份的帐户是一个 "user" 可以启动 Word,被允许访问打印机等。我已经运行 一个已知问题:我使用了 XPS 打印驱动程序,它导致弹出一个对话框。这是你不能在服务器上拥有的东西,也没有真正的方法来防止或检测它。

请记住,此服务接口仅允许发送流。如果你想添加额外的数据,你必须使用消息协定,如 Large Data and Streaming 中 msdn 中所述。在这种情况下,您的合同必须如下所示:

[MessageContract]
public class UploadStreamMessage
{
   [MessageHeader]
   public string appRef;
   [MessageBodyMember]
   public Stream data;
} 

如果你 运行 所有这一切,(压力)测试,考虑部署和安装我相信你会说服任何人这不是一个好主意。