一、实验内容
- 实验准备操作
a.下载安装java jdk 1.6或以上(笔者用的版本是1.8.0_201);
b.安装vs studio ;http://mocom.xmu.edu.cn/home/project/soft/Visual%20Studio/vs_community__2017.exe
c.熟悉IDEA或eclipse等开发环境(笔者用的版本是IDEA 2018.3.5)。
d.windows10家庭版 - 实验内容
a.构建一个com组件,该组件可以对一个字符串数组进行压缩和解压缩(压缩和解压算法自己定义,或者调用其他的库);
二、实验过程
(绝大部分过程需要使用管理员权限打开,因为涉及到写入注册表等操作)
1.构建com组件
使用管理员权限打开安装好的VS2017(右键->以管理员权限打开),在VISUAL C#下新建一个类库(.NET FRAMEWORK)名称命名为ComToJava,如下图:

双击解决方案中的Properties,修改项目的配置。按图中所示操作




此时解决方案会出现这个


将以下代码拷贝到ComToJava.cs
using System;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Text;
namespace ComToJava
{
[Guid("FC517C46-34F9-4ED5-BF5A-C977501272E7")]
public interface IMyClass
{
byte[] Compress(byte[] data);
byte[] Decompress(byte[] data);
string CompressString(string str);
string DecompressString(string str);
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("A5C4EB67-83DE-4B98-A413-5BEFD01F0774")]
[ProgId("ComToJava.Application")]
public class ComToJava : IMyClass
{
public byte[] Compress(byte[] data)
{
try
{
MemoryStream ms = new MemoryStream();
GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true);
zip.Write(data, 0, data.Length);
zip.Close();
byte[] buffer = new byte[ms.Length];
ms.Position = 0;
ms.Read(buffer, 0, buffer.Length);
ms.Close();
return buffer;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public byte[] Decompress(byte[] data)
{
try
{
MemoryStream ms = new MemoryStream(data);
GZipStream zip = new GZipStream(ms, CompressionMode.Decompress, true);
MemoryStream msreader = new MemoryStream();
byte[] buffer = new byte[0x1000];
while (true)
{
int reader = zip.Read(buffer, 0, buffer.Length);
if (reader <= 0)
{
break;
}
msreader.Write(buffer, 0, reader);
}
zip.Close();
ms.Close();
msreader.Position = 0;
buffer = msreader.ToArray();
msreader.Close();
return buffer;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public string CompressString(string str)
{
string compressString = "";
byte[] compressBeforeByte = Encoding.UTF8.GetBytes(str);
byte[] compressAfterByte = Compress(compressBeforeByte);
//compressString = Encoding.GetEncoding("UTF-8").GetString(compressAfterByte);
compressString = Convert.ToBase64String(compressAfterByte);
return compressString;
}
public string DecompressString(string str)
{
string compressString = "";
//byte[] compressBeforeByte = Encoding.GetEncoding("UTF-8").GetBytes(str);
byte[] compressBeforeByte = Convert.FromBase64String(str);
byte[] compressAfterByte = Decompress(compressBeforeByte);
compressString = Encoding.UTF8.GetString(compressAfterByte);
return compressString;
}
}
}

进入新建GUID界面,选择第5个选项,之后单击“新建GUID”,再单击“复制”,再到代码中粘贴GUID,详细见下图:

创建两个GUID到图中的地方覆盖掉

然后生成解决方案就大功告成了

如果说刚开始打开vs2017的时候没有使用管理员权限,在生成解决方案的时候就会报错,大概意思是权限不够,拒绝访问,我这边已经是生成过了,如果要重新生成解决方案,权限不够的话也会报错,如下图:

这个时候查看项目路径的bin\debug,会发现多了一个ComToJava,dll文件

然后我们要注册该文件,需要使用两个命令
gacutil /i ComToJava.dll
regasm ComToJava.dll
使用管理员权限打开开始界面中vs 2017目录下的“开发人员命令提示符”

如果没有使用管理员权限就会出现如下错误:

使用管理员权限就可以成功添加进缓存

然后我们注册该dll文件

发现图中的问题,原因是版本不匹配, 如果要正常注册dll,regasm必须能够支持dll对应的Framework的版本,这个时候我们需要调用4.0版本的regasm来注册,使用管理员权限打开cmd命令提示符(右键开始->选择“命令提示符(管理员)”),不是使用管理员权限的话又会出现权限不足的错误,输入的语句是
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe D:\缓存VS\ComToJava\ComToJava\bin\Debug\ComToJava.dll
前半部分是REGASM的路径,后半部分是dll文件的路径
结果如下图:

COM组件的创建和注册到这里就结束了
2.使用java调用COM组件
打开IDEA,新建一个project,main函数的代码为(缺少的包按ALT+ENTER导入5):
ActiveXComponent axc = new ActiveXComponent("ComToJava.Application");//获取对象
Dispatch dis = axc.getObject();
String test = "test";
System.out.println(test);
Variant v1 = Dispatch.call(dis, "CompressString", test);
System.out.println(v1);
Variant v2 = Dispatch.call(dis, "DecompressString", v1);
System.out.println(v2);
运行结果为

三、总结及一些细节
1.COM全称The Component Object Model,组件对象模型,是一种基于COM的、已编译好的软件组件,可为应用程序、操作系统以及其他组件提供服务。COM不是一种语言,而是一种标准、规范,包括一套标准API,一个标准的接口集以及COM用于支持分布式计算的网络协议。在我实验过程中,我感觉COM组件就是一个工具,做好这个工具后,你可以拿着它到其他系统、其他ide中使用。
2.GUID全称Globally Unique Identifier,全局唯一标识符。世界上的任何两台计算机都不会生成重复的 GUID 值。GUID 主要用于在拥有多个节点、多台计算机的网络或系统中,分配必须具有唯一性的标识符。在 Windows 平台上,GUID 应用非常广泛:注册表、类及接口标识、数据库、甚至自动生成的机器名、目录名等。
3.Java使用COM组件时,连接的部分为


4.字符串压缩的方法有很多种,本文选用的是GZIP,其他方法上网搜“C# 压缩字符串数组”
5.输入的字符串数组为Byte[]型,返回的是SafeArray,没办法直接输出,于是将Byte[]类型转换为String型,可以较为简便的输入输出。
网友评论