1.案发现场
java使用jacob调用com组件操作office和word,总是出现下面问题
com.jacob.com.ComFailException: Can't map name to dispid: Open
at com.jacob.com.Dispatch.invokev(Native Method)
at com.jacob.com.Dispatch.invokev(Dispatch.java:625)
at com.jacob.com.Dispatch.callN(Dispatch.java:453)
at com.jacob.com.Dispatch.call(Dispatch.java:541)
at com.xz.datacenter.ecg.word2pdf.util.COMManager.word2pdf(COMManager.java:81)
at com.xz.datacenter.ecg.word2pdf.action.TestController$1.run(TestController.java:34)
at java.lang.Thread.run(Thread.java:748)
加了代码ComThread.Release()后又出现下面问题
java.lang.IllegalStateException: Dispatch not hooked to windows memory
2.异常原因
com.jacob.com.ComFailException: Can’t map name to dispid: Open
这种异常是因为操作完成后,没有调用ComThread.Release()去释放jacob
java.lang.IllegalStateException: Dispatch not hooked to windows memory
这种异常有可能是多次调用了ComThread.Release();而引起的。
3.解决方法
单线程调用一般是不会出现问题的,出问题一般都是多线程调用,参考:JACOB调用COM组件的多线程问题
解决方法也很简单,我们要根据合理的调用ComThread.InitMTA()和ComThread.Release()。
关于ComThread.InitSTA()和ComThread.InitMTA()的区别,仍需要看完上面这篇文章。
下面这个案例我调用了两次ComThread.InitMTA(),然后在其他线程调用都美问题(初始化ActiveXComponent很耗时,一次初始化多次调用是解决性能问题)。
ComThread.startMainSTA();
for(int i=1;i<=5;i++){
new Thread(new Runnable() {
@Override
public void run() {
ComThread.InitMTA(true);
ActiveXComponent app = new ActiveXComponent("Word.Application");
app.setProperty("Visible", new Variant(false));
app.setProperty("DisplayAlerts", new Variant(false));
//初始化后放入到另外一个静态数组,方便其他线程使用调用
COMSessionFactory.sessionPool.push(app);
}
}).start();
}