通常的场景是我们用VSTO创建了一个office应用程序,里面用托管代码定义了一些方法,我们想通过外部程序打开该VSTO程序,获取VSTO对象引用,然后调用这些方法,以达到控制Office文档的目的。
直接获取失败
以下代码试图从外部程序获取VSTO对象引用,然而失败了!
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
using Microsoft.Office.Tools.Excel.Extensions;
using IExcel = Microsoft.Office.Interop.Excel;
using TExcel = Microsoft.Office.Tools.Excel;
namespace ClientApplication
{
class Program
{
static int Main(string[] args)
{
/* To avoid any problem (exception of type "Invalid format") when manipulating the
* workbook, we'll specify here the culture en-US to avoid forcing the client to
* have a language pack for excel
*/
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
//Get the application and set it visible (ie, seeing the excel front end)
IExcel.Application application = new IExcel.Application();
application.Visible = true;
//Let's create the path to the file and then : open it
string basePath = @"D:\Projects\PDA - Blog\Blog Research\VSTO - WCF\ServerApplication";
string fileName = "ServerApplication.xlsx";
IExcel.Workbook book = application.Workbooks.Open(Path.Combine(basePath, fileName),
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing);
/* Let's now use the .NET 3.5 SP1 functionality to convert an interop
* object to a VSTO object
* As it is an extension method, we could also use
* TExcel.Workbook workbook = book.GetVstoObject();
*/
TExcel.Workbook workbook = WorkbookExtensions.GetVstoObject(book);
//Let's now check that the conversion did work
Debug.Assert(workbook != null, "The conversion to VSTO did not work");
//It will fail !
return 0;
}
}
}
也就是说我们从VSTO程序外部,试图获取的VSTO对象总是为空!
原因其实很简单:
我们在试图获取另一个进程中的对象引用,而一个进程是不可以直接访问另一个进程的内存空间的。这个道理我们都知道,我们对进程间通讯的方法也耳
熟能详,什么消息发送、命名管道、匿名管道、共享内存和Socket等。令我们不解的往往是:既然能取得Interop的Appliction、
WorkBook等对象,为什么不能取得托管的VSTO对象呢?如果我们了解COM就不难理解了,.net与office的Com的互操作其实也是进程间
的一种通信机制,只不过是通过COM组件掩盖了底层的通信机制,看来进程间通信的最高境界就是通过COM组件的方式。也就是说Interop的
Appliction等对象是由COM接口公开出来的,本例中后台其实启动了一个Excel进程作为COM服务器,我们的外部程序,本例中的命令行程序充
当了一个COM客户端。而我们的VSTO对象没有公开为COM可见的形式。
如何实现从外部调用VSTO程序的托管方法呢?
答案就是使用进程间通信,有兴趣的可以参考这篇文章:http://www.pedautreppe.com/post/How-can-we-manipulate-the-VSTO-objects-when-opening-a-VSTO-document-from-command-line-.aspx ,是通过.net remoting实现的。
阅读(1130) | 评论(0) | 转发(0) |