java - JAVA中通过JACOB读取BSTR

标签 java vb.net com jacob

我正在尝试通过 JAVA 接口(interface)中的 COM 对象访问设备。

特定的调用(如制造商所述)是:

名称:ScanUSB

参数:[out] VARIANT* 序列号

用途:serialNumbers是一个指向包含BSTR数组的VARIANT的指针。

确切的调用并不重要,但我需要通过 Java 接口(interface)为其提供一个 BSTR 数组。 COM 接口(interface)的 VB 演示只需使用命令 lm_Co1.ScanUSB(snNum)Dim snNum As Object = Nothing 即可完成此操作。 snNum 中的项目随后会显示在下拉菜单中。

我正在尝试与 JACOB 一起做这件事,因为我在沟通方面非常幸运。这或多或少是我正在使用的:

import com.jacob.com.Variant;
import com.jacob.com.Dispatch;

public class JunoReader {
  public JunoReader() {
    Dispatch oOphirLink = new Dispatch("clsid:{--the id of the device here--}");
    Variant snNum = new Variant();
    Variant testing = Dispatch.call(oOphirLink,"ScanUSB", snNum);
    println(testing);
    }
}

当我运行它时,一切都会正确编译,我可以确认我正在与设备通信,但我得到的只是我输入的空变体。

我的问题是:如何通过 JAVA 接口(interface)将 BSTR 数组提供给 COM 对象?

谢谢!

最佳答案

所以,一个月零空闲时间后,我对自己的问题有了答案,这个答案就是“使用 Python”。

Python 允许用户使用 comtypes 模块访问 COM 对象,只需一个命令即可有效:

from comtypes.client import CreateObject
target_guid = CreateObject("{TARGET-COM-CLSID-HERE}")

这允许 python 与任何 COM 对象进行通信,因此 Java 不会给我带来任何麻烦。单行:target_guid.ScanUSB() 生成目标设备的序列号(u'717610',)。请注意,Python 可以轻松读取 COM 对象生成的 Unicode。

第二个技巧涉及 Python 的 COM 服务器,由 win32com 模块生成。因为COM服务器可以注册到Windows,所以我不必担心dll所在的位置。我所需要的只是 clsid。为了构建 python COM 服务器,我遵循了“服务器端 COM 和 Python 快速入门”的说明。那么这一切是什么样的?

Python 代码:

class OphirPyCOM:

    _reg_clsid_ = "{PYTHON-COM-CLSID-HERE}"
    _reg_desc_ = "Python COM server"
    _reg_progid_ = "Python COM server"
    _public_methods_ = [    'Hello', 
                            'ConnectOphir', 
                            'ScanUSB', """More methods here"""
                            ]
    _public_attrs_ = ["""Some public attributes"""]
    _readonly_attrs_ = ["""some read-only attributes"""]

    def __init__(self):
        """some variables declared here"""

    def Hello(self, who):
        """Verifies a connection"""
        return "{PYTHON-COM-CLSID-HERE}" + str(who) 

    def ConnectOphir(self,clsid):
        """Connects to the target COM Object"""
        from comtypes.client import CreateObject
        self.target_guid = CreateObject(clsid)
        return "OphirLMMeasurement object created."

    def ScanUSB(self):
        """Communicates with the target device"""
        self.connected_inst = self.target_guid.ScanUSB()
        for i in range(0,len(self.connected_inst)):
            self.inst_list.append(str(self.connected_inst[i]))
        return self.inst_list

if __name__ == "__main__":
    # use 'python com.py' to register the COM server
    # use 'python com.py --unregister' to unregister it
    print "Registering COM server..."
    import win32com.server.register
    win32com.server.register.UseCommandLine(OphirPyCOM)

我们可以使用命令行运行它并注册它。然后我们使用 JACOB 将这些值传递给 Java:

import com.jacob.com.Variant;
import com.jacob.com.Dispatch;

public class JunoReader {

  String pyClsid = "{PYTHON-COM-CLSID-HERE}"; // This is where your python COM clsid goes
  String opClsid = "{TARGET-COM-CLSID-HERE}"; // This is where your ultimate target clsid goes 

  public JunoReader() {
    _pyClsid = "clsid:" + pyClsid
    // This finds the COM object location:
    Dispatch oOphirLink = new Dispatch(_pyClsid);  
  }

  public String HandShake() {
    String _talkBack = "is connected.";
    Variant _handShake = Dispatch.call(oOphirLink,"Hello",_talkBack); // I am trying to look for the Juno...
    return (_handShake.toString());
  }

  public String ConnectOphir() {
    Variant _connectOphir = Dispatch.call(oOphirLink,"ConnectOphir", opClsid); // Connect to the target COM object
    return (_connectOphir.toString());
  }

  public String ScanUSB() {
    Variant _serialNumberList = Dispatch.call(oOphirLink,"ScanUSB"); // This scans the USB ports for devices
    return (_serialNumberList.toString());
  }
}

调用 JunoReader.ScanUSB() 会生成:717610,与预期的完全一样。实现制造商 dll 的后续方法使我能够将该设备中的数据读取到 Java 小程序中。问题解决了。

警告:每次更改源文件时,您可能需要取消注册 Python COM,然后使用不同的 clsid 重新注册。 Java 很难建立与更新代码的连接,除非我每次更改文件时都使用新的 clsid。

为什么我要花这么多时间来写这个?因为大多数与将 native 数据类型读入 Java 相关的建议都涉及 JNI 和 JNA 的某些版本。我花了几周的时间试图编译教程,但没有取得任何进展。另一方面,我昨天想到了这种方法,现在可以通过 Java 与我的设备进行通信。 Python COM 服务器提供了一种简单、直接的方法来将 Java 与 native 应用程序交互。没有UnsatisfiedLinkError,没有找不到库,没有ClasspathJAVA_HOME问题。我不需要学习 C 或 C++,所有 Python 教程都按照描述工作,无需进行必要的修改。

总而言之,如果您在将 native 数据类型读取到 Java 中时遇到困难,只需设置一个 Python COM 服务器并让 Python 的动态类型为您完成这项工作。

关于java - JAVA中通过JACOB读取BSTR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22545206/

相关文章:

java - "No suitable method found for sort(List<VarStatusMsg<? extends Number>>)"JDK错误

.net - Nhibernate 中的查询

vb.net - 如何将 "sub property"添加到类属性

windows - TYPE_E_BUFFERTOOSMALL 和 DISP_E_BUFFERTOOSMALL HRESULT 值之间有什么区别?

java - 如何在Java中实现二进制信号量类?

java - 如何将 JTable 更改为可编辑而不是在不同的选择中?

Java 从 comport 读取

asp.net - 如何在代码隐藏中获取 aspx 中的 DataKeyNames?

.net - 分配给 Excel.Application.ActivePrinter 时出现 COMException

c# - 如何使用 IPropertyNotifySink 触发从 C# 到 COM 的属性更改通知?