【问题标题】:Remoting Automation of MS Office on the server服务器上 MS Office 的远程自动化
【发布时间】:2016-01-04 15:31:07
【问题描述】:

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

我们有什么:

  • 一个没有 UI 的 Windows 7 控制台应用程序,运行着我们的 C# 应用程序,上面没有 Office 和 Interop
  • 一台 Windows 2012 服务器,上面安装了 Ms Office 2010 + Interop(当然也安装了 IIS 和 .NET)

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

  • 来自我的 C# 客户端应用程序
  • 自动安装在服务器上的“Ms office”
  • 自动化意味着将 doc 文件“保存”或“打印”到网络打印机。
  • 当然 Ms office 进程必须在服务器上运行

这种“远程办公自动化是可能的”的解决方案对我来说似乎是不可能的。但也许我错了,可能是使用 DCOM、WCF 或其他方式?

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

【问题讨论】:

  • 澄清一下,他想让你做的基本上是在你的应用程序中运行安装在远程服务器上的 Office 版本,以便客户端可以执行所有功能?还是只选择要打印的文档,通过远程服务器上安装的 Office 打印?
  • 这当然是可能的,但并不容易。但是,解决方案过于复杂,无法在此处作为答案发布。您基本上需要创建一个 WCF 或 Web 服务来打印文档并由您的客户端应用程序调用。
  • @Taegost ,我想从我的客户端应用程序执行操作(打印、保存文档),而无需在我的客户端上安装 Ms office。一种互操作的远程使用:)
  • @DirkVollmar WS 或 WCF 的解决方案是我向他提出的解决方案,但他告诉我们这太难维护了(IIS 管理、WS 声明......)。但对我来说它是最可靠的! “这当然是可能的”……这些话对我来说听起来很有趣……你有更多的细节吗??
  • @sstassin - 这是哪一个?您对“保存”一词的使用使齿轮变得紧张,因为这意味着除了打印之外还需要进行编辑。如果您只需要选择文档和打印,是的,最好在服务器上提供服务,但如果他们想在您的应用程序中实现 Office,他们最好设置一些终端服务或 Citrix...

标签: c# wcf interop ms-office .net-remoting


【解决方案1】:

正如您从 cmets 中了解到的那样,自动化任何 Office 应用程序的桌面版本是不好的,原因有几个。详细信息可在知识库文章 KB257757 Considerations for server-side Automation of Office 中找到。该文章的主要内容是:

Microsoft 目前不推荐也不支持任何无人值守、非交互式客户端应用程序或组件(包括 ASP、ASP.NET、DCOM 和 NT 服务)的 Microsoft Office 应用程序自动化,因为 Office 可能表现出不稳定Office 在此环境中运行时的行为和/或死锁。

但正如您仍然坚持的那样,请将以下示例视为一个非常简单、幼稚、不适合在生产概念验证附近使用的示例,它使您能够快速遇到知识库文章中提到的所有问题。

在一个全新的解决方案中创建一个 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 文档所需的全部内容。这在开发服务器上运行没有太多问题。如果您在 IIS 上运行此程序,您可能必须确保在 AppPool 中用作身份的帐户是可以启动 Word 的“用户”,允许访问打印机等。我已经遇到了一个已知问题:我使用了导致弹出对话框的 XPS 打印驱动程序。这是您在服务器上无法拥有的东西,也没有真正的方法可以防止或检测到这种情况。

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

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

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

【讨论】:

  • 感谢您提供非常详细的回答。我将尝试在我们的 Intranet Web 服务器上实现这一点。我知道“不在服务器模式下使用 ms office”的所有 MS 考虑因素,但现在它是打印复杂现有文档的最佳方式,并且非常准确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 2011-06-18
  • 2023-04-06
相关资源
最近更新 更多