确定我的程序实际使用了哪些 DLL and/or OCX 文件?
Determine which DLL and/or OCX files are actually used by my program?
我的软件是用VB6写的。出于诊断目的,我需要确定客户计算机上的应用程序加载和使用的实际 DLL/OCX 文件。
由于 VB6 DLL(包括 OCX 文件)是 COM 库,它们是根据注册表中的信息间接加载的。这意味着可能使用了与开发/测试环境中使用的文件不同的文件。有时在客户端环境中,如果没有此信息,这可能会导致难以诊断的故障。
(我的计划是在我的程序中构建一个诊断读数 window,以显示该程序当时正在使用的库。)
您可以使用 Dependency Walker 查找您的程序所依赖的 DLL。
但是 OCX 并不那么容易找到,因为它们是根据应用程序依赖项和通过 Windows 注册表注册的组件在 运行 时加载的。但是您必须已经知道您的应用程序引用了哪些 OCX 组件 - 从 工具 > 引用 和您调用的所有地方 CreateObject
.
可以通过多种方式建立 DLL(或 OCX 文件)的运行时依赖性。理想情况下,您需要考虑所有这些因素:
此答案特定于 VB6,但许多其他编程语言的工作方式类似。
建立运行时依赖性的机制:
传统动态链接库的编译时(不是 COM 的 DLL)
- 文件(顾名思义)根据编译结束时完成的链接过程在运行时动态加载
- 这包括使用如下语句的 VB6 代码:
Declare Function … Lib …
- (在 .NET 中这意味着调用“本机代码”)
- 识别:查看源代码。
- 无源识别:这些可以通过Dependency Walker等工具检测
在 COM DLL 的编译时
- 在 VB6 中,这称为“早期绑定”。
- 这包括已明确设置对 DLL 或 OCX 的引用的 VB6 代码。
- 请注意,依赖实际上是在 COM class 或接口 GUID 上,而不是明确地在 DLL 文件本身上。
- 识别:这些都列在项目VBP中。
- 识别(备用): 如果您没有 VBP 或源代码,通常可以通过 OLEView 中的
IMPORT
语句来揭示这些依赖关系。您可能需要在注册表中查找一些 GUID,以查看实际使用了哪些 DLL 文件。
静态链接库的编译时(不是 COM,不是 DLL)
- 库代码包含在正在编译的 EXE 或 DLL 中。因此,对任何外部事物都没有运行时依赖性。
- 据我所知,这对于 VB6 程序是不可能的。像 C 链接器这样的东西可以使用这样的库。 .NET 中的粗略等效项是使用 ILMerge 组合程序集。
传统 DLL(非 COM)的运行时
- DLL可以使用Win32任意加载API如
LoadLibrary()
.
- 识别:您必须查看源代码才能知道可能发生的情况。
- 或者,如果您没有源代码,您可以使用 Process Explorer and/or Process Monitor 等工具来观察 运行 实例并查看什么DLL 实际加载。
在 COM DLL 的运行时
- 类 可以使用例如 VB6
CreateObject()
调用任意加载。
- 在 VB6 中,这称为“后期绑定”
- 将使用哪个 DLL 来提供 class 将由进程的激活上下文决定。激活上下文由应用程序清单文件(如果有)或 Windows 注册表(VB6 程序的正常默认值)建立。
- 识别:您必须查看源代码才能知道可能发生的情况。您还需要知道运行代码的 PC 上的配置状态 - 注册了哪些 DLL 文件,假设未使用清单。
- 无源代码的替代方案:如上例
重要提示:可以链接依赖关系。所以你真的需要 "walk the links" 所有依赖关系,直到你建立一个完整的所需映射。在该映射的某处,您可以在需要部署的内容与可以依赖的操作系统或其他运行时环境提供的内容之间划一条线。 (对于 VB6 的 IMO,应该相当自由地绘制该线)。
您可能认为所有这些都使任务变得非常困难或乏味 - 我完全同意。 :)
我的软件是用VB6写的。出于诊断目的,我需要确定客户计算机上的应用程序加载和使用的实际 DLL/OCX 文件。
由于 VB6 DLL(包括 OCX 文件)是 COM 库,它们是根据注册表中的信息间接加载的。这意味着可能使用了与开发/测试环境中使用的文件不同的文件。有时在客户端环境中,如果没有此信息,这可能会导致难以诊断的故障。
(我的计划是在我的程序中构建一个诊断读数 window,以显示该程序当时正在使用的库。)
您可以使用 Dependency Walker 查找您的程序所依赖的 DLL。
但是 OCX 并不那么容易找到,因为它们是根据应用程序依赖项和通过 Windows 注册表注册的组件在 运行 时加载的。但是您必须已经知道您的应用程序引用了哪些 OCX 组件 - 从 工具 > 引用 和您调用的所有地方 CreateObject
.
可以通过多种方式建立 DLL(或 OCX 文件)的运行时依赖性。理想情况下,您需要考虑所有这些因素:
此答案特定于 VB6,但许多其他编程语言的工作方式类似。
建立运行时依赖性的机制:
传统动态链接库的编译时(不是 COM 的 DLL)
- 文件(顾名思义)根据编译结束时完成的链接过程在运行时动态加载
- 这包括使用如下语句的 VB6 代码:
Declare Function … Lib …
- (在 .NET 中这意味着调用“本机代码”)
- 识别:查看源代码。
- 无源识别:这些可以通过Dependency Walker等工具检测
在 COM DLL 的编译时
- 在 VB6 中,这称为“早期绑定”。
- 这包括已明确设置对 DLL 或 OCX 的引用的 VB6 代码。
- 请注意,依赖实际上是在 COM class 或接口 GUID 上,而不是明确地在 DLL 文件本身上。
- 识别:这些都列在项目VBP中。
- 识别(备用): 如果您没有 VBP 或源代码,通常可以通过 OLEView 中的
IMPORT
语句来揭示这些依赖关系。您可能需要在注册表中查找一些 GUID,以查看实际使用了哪些 DLL 文件。
静态链接库的编译时(不是 COM,不是 DLL)
- 库代码包含在正在编译的 EXE 或 DLL 中。因此,对任何外部事物都没有运行时依赖性。
- 据我所知,这对于 VB6 程序是不可能的。像 C 链接器这样的东西可以使用这样的库。 .NET 中的粗略等效项是使用 ILMerge 组合程序集。
传统 DLL(非 COM)的运行时
- DLL可以使用Win32任意加载API如
LoadLibrary()
. - 识别:您必须查看源代码才能知道可能发生的情况。
- 或者,如果您没有源代码,您可以使用 Process Explorer and/or Process Monitor 等工具来观察 运行 实例并查看什么DLL 实际加载。
在 COM DLL 的运行时
- 类 可以使用例如 VB6
CreateObject()
调用任意加载。 - 在 VB6 中,这称为“后期绑定”
- 将使用哪个 DLL 来提供 class 将由进程的激活上下文决定。激活上下文由应用程序清单文件(如果有)或 Windows 注册表(VB6 程序的正常默认值)建立。
- 识别:您必须查看源代码才能知道可能发生的情况。您还需要知道运行代码的 PC 上的配置状态 - 注册了哪些 DLL 文件,假设未使用清单。
- 无源代码的替代方案:如上例
重要提示:可以链接依赖关系。所以你真的需要 "walk the links" 所有依赖关系,直到你建立一个完整的所需映射。在该映射的某处,您可以在需要部署的内容与可以依赖的操作系统或其他运行时环境提供的内容之间划一条线。 (对于 VB6 的 IMO,应该相当自由地绘制该线)。
您可能认为所有这些都使任务变得非常困难或乏味 - 我完全同意。 :)