【问题标题】:Reading a DLL (or VB6) file from VBScript从 VBScript 读取 DLL(或 VB6)文件
【发布时间】:2021-07-17 06:09:57
【问题描述】:

我正在尝试使用 VBScript 访问 VBA 文件(或 DLL)中的函数。我有点不知所措,而且我通常不会使用这两种语言,所以我会解释一下情况,以防有更好的解决方案。

我有一个仪器,它有一个内部类似 VBScript 的窗口(它有一些 VBScript 中没有的功能,例如“Include...End Include”语句),可用于自动化仪器操作,我'我试图将它与相机结合使用。对于相机,该公司提供了 VB (atmcd32d.bas) 和 C++ (atmcd32d.cpp) 文件,其中包含与 DLL 文件 (atmcd32d.dll) 通信所需的所有函数(例如,GetTemperature、StartAcquisition 等),我假设向相机发送命令。如果我使用 C++ 或 VBA,我假设我可以直接包含这些文件,这将使我的代码能够访问控制相机所需的命令。但是,主要仪器软件使用的脚本语言最接近VBScript。如果我将文件更改为 .txt,该脚本允许我包含该文件,但是当它到达不属于 VBScript 的“属性”、“枚举”和“声明函数”之类的命令时,它当然会失败。

首先,我想知道是否有更好的方法来运行 .bas 文件。

另外,我想我可以尝试从 .bas 文件中翻译我需要的函数,这样我就可以从 VBScript 与 DLL 进行通信。这将一个问题变成了两个问题。 它产生的第一个问题是翻译,我不确定这是否是一种现实的方法。因为是750行的文件,所以想先问问别人。

第二个问题是如何与 DLL 通信。我找到了一个关于使用 VBScript 与 DLL 通信的页面:How to call C# DLL function from VBScript

我尝试使用这种方法。对于我的情况,我假设 DLL 已经注册,因为它是与相机软件一起安装的,所以我只需要使用:

Set obj = CreateObject("C:\MyPath\atmcd32d.dll")

访问相机功能。但是,如果我只使用该行运行脚本,则会收到消息“ActiveX 组件无法创建对象”。这是否意味着 DLL 未注册?还是我犯了其他错误?

对于这个令人费解的问题,我深表歉意,但考虑到我已经摸不着头脑,我想我应该寻求帮助,然后再深入挖掘错误的方向。

【问题讨论】:

  • CreateObject 用于创建在您注册的 dll 中定义的类的实例。因为它已注册,所以您不需要提供 dll 的路径。类的完全限定名就足够了。 (这也是链接问题的答案所说的)
  • this answer 中有很多有用的信息,其中包括 COM DLL 注册以及如何检查它是否在正确的 Windows 子系统中注册。还有一个清单可供通读,这将帮助您诊断问题。
  • 这能回答你的问题吗? Using DLLs in VBScript
  • 如果 atmcd32d.bas 包含 "Declare Function..." 行,例如 Declare Function Initialize Lib "atmcd32d.dll" (ByVal dirName As String) 只要 atmcd32d.dll 不是 ActiveX/COM dll所以 CreateObject 函数不能用于与 ATMCD32D.DLL 的接口。从neurophysics.ucsd.edu/Manuals/Andor%20Technology/…查看 Andor SDK 用户指南
  • ATMCD32D.DLL 的 ActiveX/COM 包装器(仅用于必要的功能)可以解决 CreateObject 函数的使用问题。

标签: dll vbscript vb6


【解决方案1】:

我从您的 Andor 相机的文档中得到的印象 (https://neurophysics.ucsd.edu/Manuals/Andor%20Technology/Andor_Software_Development_Kit.pdf) 是 DLL 不能直接从 VBScript 访问。

文档是这样说的:

在构建您自己的项目时,您必须包含文件 ATMCD32D.BAS。 此文件包含用于接口的 Andor SDK 函数原型 使用动态链接库 ATMCD32D.DLL

他们在这里指的不是 VBScript,而可能是更“标准”的 BASIC 版本,例如 VB.NET 或现在相当古老的 VB6(“经典”VB)。这些语言具有直接调用 DLL 中的函数的特性。

另一方面,VBSCript 显然只能访问支持 COM 规范的外部 DLL。考虑 COM 的一种方式是,它是一种使对象(或类)可从 DLL 访问的标准方法——但不仅仅是像 C 这样的语言那样的普通函数。然而,他们的 DLL 似乎并不直接支持 COM。 (但要仔细检查,请参阅 https://stackoverflow.com/a/3011424/3195477https://stackoverflow.com/a/49920874/3195477)。

因此,您需要编写自己的代码,该代码将充当 Andor DLL 中函数的包装器。该包装 DLL 需要提供 COM 类,这些类依次调用实际的 Andor DLL 函数。这个包装器可以用任何能够生成 COM 可见 DLL 的语言编写。建议您为此使用 VB.NET,因为这可能是合并ATMCD32D.BAS 文件的最简单途径。该文件的语法可能与 VB.NET 完全兼容(但我自己无法验证)。

Visual Studio 不仅能够为您生成这样的 DLL,而且还能够使用 .NET 工具或多或少地自动生成您需要的 COM 层。在 VB.NET 项目中,您需要创建(至少)一个您将从 VBScript 调用的类。该类应该具有与您需要使用的 Andor DLL 中的任何函数相对应的函数。您不必将它们全部包括在内 - 事实上,作为第一步,我会做最基本的事情,您可以将其视为概念证明,以确认所有“接线”是正确的。类函数可以只匹配 DLL 函数的名称和参数,或者您可以根据需要添加一些额外的逻辑。

总之,我将遵循以下步骤:

  1. 运行 Visual Studio
  2. 新建一个 VB.NET 类库项目
  3. 在项目属性中,确保将其设置为注册为 COM 可见(我忘记了此选项的确切措辞)
  4. 添加一个类,比如说WrapperClass
  5. 或许您可以将 .BAS 文件的内容复制到此类中。我希望它应该包含一堆DECLARE FUNCTION 语句。
  6. 将 public SUBs 或 FUNCTIONs 添加到您的类中,它们只需调用 DECLAREed 函数。
  7. 确保该类应用了<COMVisible(true)> 属性,我也会为此使用<ClassInterface(ClassInterfaceType.AutoDual)>
  8. 在 Visual Studio 中编译类库项目。如果一切设置正确,它还会注册它为您创建的 DLL。
  9. 您可能需要将 Andor DLL 复制到与包装 DLL 相同的位置(通常为 project\bin\debug\ 文件夹)
  10. 在 VBScript 中,您可以执行以下操作:
Set obj = CreateObject("WrapperClass")   
Call obj.WrapperFunction1 ...

(我倾向于使用 C# 而不是 VB.NET,但我认为上面的策略是正确的,这些细节几乎是相同的。)

做好准备,解决实施中的任何问题可能需要一些时间。你必须用 COM 做的事情并不太复杂,但有很多小陷阱。此外,这还假设了您正在使用的 VBScript 环境的专有性质。

如果您没有在将运行 VBScript 程序的同一台 PC 上运行 Visual Studio,那么您将需要执行一些额外的步骤来手动复制并在该 PC 上注册包装 DLL(以便 CreateObject 可以工作)。在这种情况下也可能需要 .NET 更新。如果您能找出那台 PC 上已有的 .NET 版本,我只需将包装 DLL 设置为针对所述版本进行编译;对于您需要编写的代码,它实际上可能并不重要。

【讨论】:

  • 我正在逐步实现这一目标。为了练习,我在 vb.net 中创建了一个 DLL 来添加 2 个数字并使用 Register for COM interopMake assembly COM-visible 注册它。我找不到ClassInterfaceType,所以我跳过了它。我可以创建一个 VB.Net 控制台函数,将两个数字发送到 addition DLL 并打印结果,但它只有在我使用 Visual Studio 中的 Add Reference 菜单项引用 DLL 时才有效。由于Add Reference 不是VBScript 窗口中的选项,我尝试在没有它的情况下使用CreateObject,但我得到“ActiveX 组件无法创建对象”。
  • 您可能只是在您的 VB 源文件中缺少Imports System.Runtime.InteropServices?这应该可以找到ClassInterfaceType。您的方法是合理的,测试CreateObject 可以实例化您的类正是您想要做的。当它起作用时,你就会知道所有的“管道”都是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2011-03-30
  • 2014-12-11
相关资源
最近更新 更多