服务器上 MS Office 的远程自动化
Remoting Automation of MS Office on the server
我警告你,你的问题对很多人来说似乎很奇怪:) 但我必须 post 因为我的项目经理告诉我存在技术解决方案,即使对我来说不是。
我们有:
- 一个 Windows 7 控制台应用程序,没有 UI,我们的 C# 应用程序 运行ning,上面没有 Office 和 Interop
- a Windows 2012 服务器,上面安装了 Ms Office 2010 + Interop(当然还有 IIS 和 .NET)
我的 PM 想要什么(我告诉他这是不可能的):
- 来自我的 C# 客户端应用程序
- 在服务器上安装 "Ms office" 自动化
- 自动化意味着 "Save" 或 "print" 将 doc 文件发送到网络打印机。
- 当然 Ms office 进程必须 运行 在服务器上
这种"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;
}
如果你 运行 所有这一切,(压力)测试,考虑部署和安装我相信你会说服任何人这不是一个好主意。
我警告你,你的问题对很多人来说似乎很奇怪:) 但我必须 post 因为我的项目经理告诉我存在技术解决方案,即使对我来说不是。
我们有:
- 一个 Windows 7 控制台应用程序,没有 UI,我们的 C# 应用程序 运行ning,上面没有 Office 和 Interop
- a Windows 2012 服务器,上面安装了 Ms Office 2010 + Interop(当然还有 IIS 和 .NET)
我的 PM 想要什么(我告诉他这是不可能的):
- 来自我的 C# 客户端应用程序
- 在服务器上安装 "Ms office" 自动化
- 自动化意味着 "Save" 或 "print" 将 doc 文件发送到网络打印机。
- 当然 Ms office 进程必须 运行 在服务器上
这种"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;
}
如果你 运行 所有这一切,(压力)测试,考虑部署和安装我相信你会说服任何人这不是一个好主意。