实现通过COM组件方式实现java调用C#写的DLL文件的完整demo
最近因为工作需要,客户那边工程师使用的是java语言开发的程序,我们这边平台中是用c#语言开发的,因为有些操作必须统一,所以我在网上查找解决方法,自己也实践过,在这里做个笔记吧,分享一下。
一、使用c#编写com组件
开发环境 :vs2017
1、新建工程:calctest(类库项目,根据自己喜好需要取工程名,框架我这里使用的是:.net framework 4 ,你可以根据自己的来选。 (注:下面红色框和箭头和需要注意的地方)
2、右键项目属性,点击项目属性,看到下面这个界面,点击红色框框"程序集信息,使程序集com可见,打上勾,如下图所示
程序集中其他信息可以根据个人喜好可写可不写。
3、选择生成看到以下界面,平台目标选择:x64, 为com互操作注册(c) 勾上,如下图操作。
4、接下来是设置强签名,要以管理员的身份运行
①.找到visual studio command prompt (vs2017 开发人员命令提示)
输入命令:sn -k d:/calccomkey.snk
这里我生成的calccomkey.snk 文件放在d盘,注意选择你自己的保存路径。
vs2017 开发人员命令提示工具的路径是安装vs2017 路径下,你可以自己找一下,每个人安装位置不一样。
比如我的是 : c:\programdata\microsoft\windows\start menu\programs\visual studio 2017\visual studio tools
5、在签名 标签中选中 为程序集签名,选择刚刚生成的强名称文件calccomkey.snk 。
6、创建guid
通过点击工具 => 创建guid => 选择4 => new guid => copy => 替换下面 c#代码中的两个 guid 值
创建guid,新建复制,粘贴到代码中去就可以,把代码中那两个都替换掉。
using system; using system.collections.generic; using system.linq; using system.runtime.interopservices; using system.text; namespace calctest { [guid("68e2a6fd-f437-4107-a6db-e78714ec8d8b")] //guid值 interface icalc { [dispid(1)] int add(int a, int b); //返回的int值,与需要调用的类的方法名一致。 } [guid("60d60ee5-eaf3-482c-be33-ded6be635111"), classinterface(classinterfacetype.none)] //guid值 public class calc : icalc //类名,接口名 ,必须定义接口 { public calc() { } //定义具有两个参数的方法,返回计算结果。根据各自需要定义。 public int add(int a, int b) { return a+b; } } }
7、编译生成程序,debug目录中会生成 calctest.dll 和calctest.tlb。
二、java调用c#编写com组件
一、准备工作
1、刚刚上文中我们生成的两个文件,calctest.dll 、 calctest.tlb,先保存起来,一会儿会用到。
命名空间为:calctest、类名为:calc
2、jacob下载,可以自主下载,这里提供一个,下面是百度网盘的地址和提取码:
链接:https://pan.baidu.com/s/1u_2ndpqvmscsb9_ficw9ig
提取码:s60u
二、实现步骤
1、将calctest.dll、calctest.tlb复制到java开发环境中,java环境中需要安装对应版本的.net framework
注:java开发环境指jdk下的bin目录,我的是win7的系统,默认就安装了.net framework 4.0
2、在java开发环境中注册新生成的com组件,在客户环境中,通过regasm.exe注册com组件。
regasm.exe默认安装路径为:c:\windows\microsoft.net\framework\v2.0.50727
注:因为上面我们选择的是x64平台,因此框架是选择framework64,路径为:
c:\windows\microsoft.net\framework64\v4.0.30319
还有步骤1的意思就是,把calctest.dll、calctest.tlb复制到这个路径下面c:\windows\microsoft.net\framework64\v4.0.30319
注:图片中的invoketest.dll和invoke.tlb就是我们上文的calctest.dll、calctest.tlb
①、按下win+r,输入cmd进入控制面板
②、输入 cd c:\windows\microsoft.net\framework64\v4.0.30319
③、接下来,手动注册com方法:运行命令(管理员身份运行)
④、regasm calctest.dll /calctest.tlb
出现以下界面说明注册成功:
注:图片中的invoketest.dll和invoke.tlb就是我们上文的calctest.dll、calctest.tlb
3、强签名的dll文件添加到缓存中
1、首先找到gacutil,路径为:c:\program files (x86)\microsoft sdks\windows\v10.0a\bin\netfx 4.6.1 tools
注:也有可能在这里路径下面找不到gacutil,那么就去下载一个或者找一下其他地方的复制过来,我一开始就没有这个bin文件夹,从其他地方拷贝过来的。
注:图片中的invoketest.dll和invoke.tlb就是我们上文的calctest.dll、calctest.tlb
2、接下来就是要将dll添加到缓存中
①、按下win+r,输入cmd进入控制面板
②、输入
cd c:\program files (x86)\microsoft sdks\windows\v10.0a\bin\netfx 4.6.1 tools
③、执行命令: 执行这个命令需要invoketest.dll 具有强名称
gacutil -i c:\program files\java\jdk1.8.0_181\bin\invoketest.dll
注:上面这个路径因人而异,找到你自己jdk的存放路径,把invoketest.dll、invoketest.tlb放到bin文件夹下面。
注:图片中的invoketest.dll和invoke.tlb就是我们上文的calctest.dll、calctest.tlb
ok,dll添加到缓存中的操作就完成了,看到以下界面就说明成功添加了
或者
4、查看注册表regedit,hkey_classes_root中是否有invoketest.mymd5 项,如果有说明注册com成功。如果没有,请重新注册。重复上面过程。
查看注册表,不知道怎么操作的,下面链接可以打开看,或者自己上网查。
看到以下界面说明注册成功了
注:图片中的invoketest.mymd5就是我们上文的calctest.calc,因为节省时间,我上文给大家演示了一遍,下面这个是按照我实践过的例子贴的经验,
三、java项目调用
1、新建项目,引用jacob.jar
2、实现,直接贴代码
package test; //=================导包======================= import com.jacob.activex.activexcomponent; import com.jacob.com.comthread; import com.jacob.com.dispatch; import com.jacob.com.variant; //=================导包======================= public class main { public static void main(string[] args) { // todo auto-generated method stub try { comthread.initsta(); activexcomponent dotnetcom = null; //需要调用的c#代码中的命名空间名和类名。 dotnetcom = new activexcomponent("calctest.calc"); //需要调用的方法名和参数值 variant var = dispatch.call(dotnetcom,"add",1,2); string str2 = var2.tostring(); //返回需要的字符串 system.out.println(str2.tostring());//打印结果,结果等于3 } catch (exception ex) { ex.printstacktrace(); }
finally { comthread.release(); } } }
声明:下面操作主要分为两部分,第一部分使用c#编写com为了写这篇文章我是新建的操作demo,
第二部分java调用c#编写的com组件,因为是工作时的demo,因为当时有给客户写了使用说明,在这里拿一些截图出来用一下,为了节省时间,我就不再操作一遍了,如有不理解的可以留言。
ok,对于整个操作过程就分享到这里了,如果有不理解的,或者我有讲的不对的请帮忙指出,谢谢。
上一篇: C# -- 使用缓冲区进行文件下载操作
下一篇: Thinkphp5 自定义上传文件名