JAVA通过jacob调用ocx_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > JAVA通过jacob调用ocx

JAVA通过jacob调用ocx

 2014/12/4 22:05:39  zyp307  程序员俱乐部  我要评论(0)
  • 摘要:下载jacob包网址http://sourceforge.net/projects/jacob-project/?source=directory这个包中有jacob-1.17-M2-x64.dll和jacob-1.17-M2-x86.dll两个dll和jacob.jar一个jar包,两个dll一个是64位一个是32位,这个对应的是jdk,不是指系统Jacob包放置位置如果系统是64位的就将dll文件放到C:\Windows\SysWOW64下,如果系统是32位的就将dll文件放到C
  • 标签:Java

下载jacob

class="p0">网址http://sourceforge.net/projects/jacob-project/?source=directory

这个包中有jacob-1.17-M2-x64.dlljacob-1.17-M2-x86.dll两个dlljacob.jar一个jar包,两个dll一个是64位一个是32位,这个对应的是jdk,不是指系统

Jacob包放置位置

如果系统是64位的就将dll文件放到C:\Windows\SysWOW64下,如果系统是32位的就将dll文件放到C:\Windows\System32

Jar文件可以放到jdk下也可以加载到自己工程的外部jar包,我是加载到工程中的

注册ocx插件

注册ocx插件,建议64位系统放到C:\Windows\SysWOW64下,32位系统放到放到C:\Windows\System32下,

打开命令行,通过命令regsvr32?C:\Windows\SysWOW64\mc2.ocx进行注册,C:\Windows\SysWOW64\为放置ocx的目录,mc2.ocxocx名称,注册成功失败都会有窗口提示,这是windows的事情,此处不再说明。

卸载注册命令可以用regsvr32?/u?C:\Windows\SysWOW64\mc2.ocx

新建java工程

新建java工程,将jacob.jar放到工程中新建的lib目录下,右键工程名打开配置环境变量窗口,导入jar

?

代码举例

?

package com.hsh.ocx;
 
import com.jacob.activeX.ActiveXComponent;
import com.jacob.activeX.ActiveXDispatchEvents;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents;
import com.jacob.com.InvocationProxy;
import com.jacob.com.Variant;
 
public class JavaOcx {
 
public static void main(String[] args) throws InterruptedException {
 
//HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{74E58985-15BD-483D-A281-4F6D4BB6387E}
 
ComThread.InitMTA(true); 
// 通过ProgID调用OCX控件,组件的ProgID对应注册表中mc2.ocx注册后的ProgID值,可以打开注册表查找ocx文件名找到对应的值
//ActiveXComponent com = new ActiveXComponent("组件的ProgID") ;
ActiveXComponent com = new ActiveXComponent("MC2.Mc2Ctrl.1") ;
//通过CLSID调用OCX控件
//ActiveXComponent com = new ActiveXComponent("CLSID:74E58985-15BD-483D-A281-4F6D4BB6387E") ;
Dispatch disp = (Dispatch) com.getObject();
/**
        先调用Init方法进行初始化	 
  [id(1)] long Init(BSTR AccountNo, BSTR Extno, BSTR Password);
       既可以用接口名称"Init"调用,也可以用id(1)来调用
          Init为ocx插件中对应的方法名,accountno,extno,password为该方法中对应的参数
*/
String accountno="*********";
String extno = "**";
String password = "******";
int Init = Dispatch.call(disp,"Init",new Variant(accountno),new Variant(extno),new Variant(password)).getInt();
//int Init = Dispatch.call(disp,"Init",accountno,extno,password).getInt();//用接口名称"Init"调用
//int Init = Dispatch.call(disp,1,accountno,extno,password).getInt();//用id(1)来调用
System.out.println("初始化结果为"+Init);
 
//初始化后需要等一下,不能马上调用其他接口,所以这里加了延时以等待初始化结束
Thread.sleep(3000);
//调用isLogin接口查看是否还在登录状态,只有在登录状态才可进行其他操作
//[id(1)] LoginEvent(iStatus,szVoipNo,szServiceTel);
Boolean isLogin2 =  Dispatch.call(disp,2).getBoolean();
System.out.println("登录结果为"+isLogin2);
        If(isLogin2){
//[id(11)]long SendShortMessage(BSTR szRecvTelNo, BSTR szContent);
int SendShortMessage = Dispatch.call(disp,11,"********","********").getInt();
System.out.println("短信发送结果为"+SendShortMessage);
}
//释放线程
ComThread.Release(); 
}
 
}

?

?

问题总结

常见的几个错误

1java.lang.UnsatisfiedLinkError:?no?jacob?in?java.library.path

这个是没有找到jacob.dll,需要把对应的dll放到对应目录下

2Exception?in?thread?"main"?com.jacob.com.ComFailException:?Can't?get?object?clsid?from?progid

这个应该是注册表中找到的progid不对,检查一下

3Exception?in?thread?"main"?com.jacob.com.ComFailException:?A?COM?exception?has?been?encountered:

At?Invoke?of:?isLogin

Description:?灾难性故障

?

at?com.jacob.com.Dispatch.invokev(Native?Method)

at?com.jacob.com.Dispatch.invokev(Dispatch.java:804)

at?com.jacob.com.Dispatch.callN(Dispatch.java:440)

at?com.jacob.com.Dispatch.call(Dispatch.java:510)

at?com.vflow.sms.InitOcxFunctions.isLogin(InitOcxFunctions.java:36)

at?com.vflow.test.TestOcx.main(TestOcx.java:14)

?

原因是:?这个错误是由ActiveX结构设计造成的。

Ole4.0版本之前,外部程序是可以直接调用OCX中方法的。Ole4.0之后,每次调用控件中的方法,系统会自动检查是否答应调用,即运行COleControl.IsInvokeAllowed?(DISPID)

该方法检查控件是否正确的初始化或者是否通过持久存储接口正确加载,假如两个条件有一个满足,即返回TRUE,否则返回FALSE

当控件在MFC中使用时,很多细节,如初始化,都被过滤了,这样,大多数用户都不会碰到这个题目。但是,当我们从CC++dll中调用控件时,不满足上述条件,该方法返回FALSE,这时候再调用任何控件方法,都会出现上述异常

OCX控件中,重写COleControl.IsInvokeAllowed?(DISPID)方法,即在控件的CMyNameCtrl中增加一个方法

BOOL?CMyNameCtrl::IsInvokeAllowed?(DISPID)

?{

?return?TRUE;

?}?

4An?unexpected?error?has?been?detected?by?Java?Runtime?Environment:

#

#??EXCEPTION_ACCESS_VIOLATION?(0xc0000005)?at?pc=0x77c9e3be,?pid=1140,?tid=4900

#

#?Java?VM:?Java?HotSpot(TM)?Client?VM?(11.3-b02?mixed?mode?windows-x86)

#?Problematic?frame:

#?C??[ntdll.dll+0x2e3be]

#

#?If?you?would?like?to?submit?a?bug?report,?please?visit:

#???http://java.sun.com/webapps/bugreport/crash.jsp

#?The?crash?happened?outside?the?Java?Virtual?Machine?in?native?code.

#?See?problematic?frame?for?where?to?report?the?bug.

#

这个应该是jacob版本问题,我开始用的一个jacob报这错误,后下载了新版本的重试就可以了

发表评论
用户名: 匿名