包装DLL-了解导入失败的原因

Wrapping a DLL - Understanding why Import Fails

本文关键字:失败 导入 DLL- 了解 包装      更新时间:2023-10-16

背景

我有一个嵌入式系统,它运行一个最初用C++编写并在Visual Studio中编译的应用程序,它产生了一个可执行文件和30多个DLL。这些库不能在VS对象浏览器或其他工具(如P/Invoke Interop Assistant)中浏览。

在Dependency Walker中加载一些dll显示,所有dll都在依赖关系树深处缺少一些依赖关系(cdfview.dlldwmapi.dllw32topl.dll..),但根据这个问题,这可能不是问题。

我有一些源代码文件,以及所有编译的DLL。应用程序当前运行时没有问题,这表明不存在真正的依赖性问题。

我正在尝试调用一些库函数,并最终使用C#制作包装器,但即使是最简单的函数也无法成功导入和调用。我总是收到以下错误:

无法加载DLL"dllName.DLL":动态链接库(DLL)初始化例程失败。(HRESULT:0x8007045A的异常)

示例代码[已编辑]

从C++源代码头文件中,我有以下声明:

#define OB_API __declspec(dllexport) __cdecl 
typedef unsigned long DWORD;  // From windef.h
typedef DWORD OBSTATUS;
OBSTATUS OB_API TestObj(void);

在C++源代码文件中,给出了以下定义(似乎总是返回true):

BOOL WINAPI DllMain(HANDLE  /* hModule */, 
DWORD   ul_reason_for_call, 
LPVOID  /* lpReserved */
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}

在我的C#应用程序类中,我添加了以下声明:

[DllImport(@"dllName.dll", CallingConvention=CallingConvention.Cdecl)
public static extern ulong TestObj();

DLL和C#应用程序二进制文件位于同一目录中。

问题

通过对错误的研究,似乎有很多原因可以引发这个特定的异常,我想知道如何进一步解决这类问题。

有什么方法可以获得关于初始化例程失败原因的更详细信息吗?

(注意:目标系统正在运行.NET framework 2.0)

您正在加载的DLL包含一个DllMain()函数。这很常见,这样的函数初始化DLL的状态。Windows确保每当加载DLL时都会调用此函数,这将在您第一次pinvoke该DLL导出的函数时自动发生。

问题是,该函数返回FALSE表示无法正确初始化DLL。当然,这并不能提供关于为什么返回FALSE的所有信息。Windows除了生成错误1114,error_DLL_INIT_FAILED之外,什么也做不了。如果DLL本身没有输出任何诊断,那么除了调试代码之外,您什么都不能做。从Project+Properties的"调试"选项卡开始,勾选"启用非托管代码调试"选项。

祈祷您在"输出"窗口中看到一条消息。几率不是很大。如果你没有DLL的源代码,那么你需要DLL的供应商或作者的帮助。给他一份这样失败的测试项目的副本。

也许原因是需要安装旧的Net Framework版本,如2.0、3.0、3.5……这对我来说很有效:D