c#WinForm程序调用vsto动态库,已解决
最近做一个vsto的项目,涉及到Form程序调用vsto动态库,弄了半天,搜了很多资料终于搞定了,把积累写下来备以后用。
相关网址:
https://stackoverflow.com/questions/10875278/vsto-add-ins-comaddins-and-requestcomaddinautomationservice
https://blogs.msdn.microsoft.com/andreww/2008/08/11/why-your-comaddin-object-should-derive-from-standardolemarshalobject/
https://blogs.msdn.microsoft.com/andreww/2007/01/15/vsto-add-ins-comaddins-and-requestcomaddinautomationservice/
Demo:
1. 建立一个word外接程序(addin)
我的demo建的是WordVSTOTest工程,建好以后在addin.cs文件中添加一个类变量和一个函数。这个函数是必须的。
namespace WordVSTOTest { public partial class ThisAddIn { private AddinUtilities addinUtilities; protected override object RequestComAddInAutomationService() { if (addinUtilities == null) { addinUtilities = new AddinUtilities(); } return addinUtilities; } } }
注意到AddinUtilities 没有定义,是的,这是个自定义类,名字随便,但要保持一致,里面要封装你要导出的供外部调用的函数。
2. 添加一个类
demo的类名叫AddinUtilities,添加如下代码:
using System.Runtime.InteropServices;
namespace WordVSTOTest { [ComVisible(true)] [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface IAddinUtilities { void test(); } [ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] public class AddinUtilities : StandardOleMarshalObject, IAddinUtilities { void test() { MessageBox.Show("Hello World"); } } }
这里定义一个接口类型,接口类型里面的函数就是要导出供外部调用的函数,需要什么函数就些什么函数,和普通函数无区别,然后我们的AddinUtilities类要继承这个接口,最后依次实现定义的函数就可以了。我这里是导出了test函数,简单弹个框。
3. 编译
这个编译需要设置一下,不然会有很多莫名其妙的错误,首先vs要用管理员启动,然后转到工程属性-->build,在“输出”栏有个
“为COM互操作注册”的复选框,要勾选这个,最后编译。编译过程中如果要提示还有类似没有注册的错误,要用regasm.exe
注册一下就行了。电脑里搜索到regasm.exe所在的目录,cmd下转到该目录,使用命令:regasm.exe dll绝对路径 /参数。
编译好的dll要在winForm工程里面使用。
好了vsto这边的工作就做完了,下面转到我们的Form测试工程。
4. 建立一个WinForm工程
Demo为WinFormTest工程,建好以后,在form上拖一个button控件,双击button直接转到click函数处:写入一下代码:
public Word.Application app; public IAddinUtilities utils; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { app = new Word.Application(); string str = app.Name; app.Visible = false; object addinName = "WordVSTOTest"; COMAddIn addin = app.COMAddIns.Item(ref addinName); utils = (IAddinUtilities)addin.Object; utils.test(); //如果没有这个Quit的话,任务管理器的WINWORD.exe不会退出,越来越多。 ((Word._Application)app).Quit(); System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app); }
注意工程需要using以下几项:
using WordVSTOTest;
using Word = Microsoft.Office.Interop.Word;
using Microsoft.Office.Core;
引入这些后才可以编译通过。
简单看一下工程截图:
查看运行结果:
5. 结束。
理解这个调用过程还需要对COM有所了解,不明白原理,抄来抄去到时候出现bug也难排查,就到这里吧。