如果我在运行时使用 unix 上的 dlopen() 或 Windows 上的 LoadLibrary() 加载 dll 或 so 库,我是否需要确保库中的符号与程序中的符号名称不同?另外是否可以加载定义相同函数的多个共享库?
编辑:我特别询问运行时动态链接。
我在我的C++应用程序的一个DLL中遇到了非常奇怪的行为.它工作并加载正常,直到我在DLL的主文件中使用#include包含单个文件.然后我收到此错误消息:
从D加载组件:/Targets/bin/MatrixWorkset.dll无法加载"D:/Targets/bin/MatrixWorkset.dll":无法加载库MatrixWorkset:对内存位置的无效访问.
现在我搜索并搜索了代码和谷歌,我无法弄清楚发生了什么.到目前为止,一切都在一个DLL中,我决定将它分成两个较小的DLL.导致问题的文件是另一个第二个库(加载正常)的一部分.
真的很感激任何想法.谢谢,哈科
我们想挂钩调用LoadLibrary以下载未找到的程序集.我们有一个处理托管程序集的ResolveAssembly处理程序,但我们还需要处理非托管程序集.
我们尝试通过"编写Microsoft Windows编程应用程序"中指定的技术重写import表来挂钩LoadLibrary调用,但是当我们调用WriteProcessMemory()时,我们得到一个权限被拒绝错误(998).(是的,我们正在使用提升的私人运行)
在加载CLR时是否有人成功重写了import表?谁能指出我正确的方向?
更新:我们解决了权限被拒绝的问题,但现在当我们迭代混合程序集的Imports表(托管+非托管)时,我们找到的唯一条目是mscoree.dll.有谁知道如何找到原生进口?(我们在C++/CLI中工作).
在我从XP迁移到Vista之后,我意识到我的C#程序不起作用.
这就是这样的情况:我在C#应用程序中编写了一个C++ DLL.这个DLL在XP中运行良好,但是当我转移到Vista时,它不再适用于C#.
我在Delphi中测试它,工作正常,但C# - 没有.
我写了额外的代码,以便在C#中更容易检查.
if (LoadLibrary("blowfish.dll") == 0)
{
Misc.LogToFile("error", true);
Application.Exit();
}
Run Code Online (Sandbox Code Playgroud)
它不需要C++运行时,因为它使用库编译并且它在Vista上的Delphi中工作,但不适用于C#.
问题出在哪里?
提前致谢.
到目前为止,我有一些插件机制,我使用LoadLibrary和GetProcAddress加载dll来创建一个具体对象并返回一个公共接口.这工作正常,直到我决定其中一个dll应该是一个exe.
LoadLibrary的文档说它也可以用于exe,所以我试了一下.作为GetProcAddress,exe加载没有错误.但是当我尝试调用我的具体对象的构造函数时,我得到了一个访问冲突.
我认为这会发生,因为加载exe不会加载它使用的所有dll.所以我尝试使用LoadLibrary加载它们,但我得到了同样的错误.有什么建议吗?
这是我的代码(混合C++/CLI):
Interface* MCFactory::LoadInstanceFromAssembly( String ^ concreteAssemblyName, String ^ param ){
string fullPathToAssembly = "";
fullPathToAssembly += FileSystem::GetPathToProgramDirectory();
fullPathToAssembly += "\\" + marshal_as<string>(concreteAssemblyName);
MODULE hDLL = AssemblyLoader::GetInstance().LoadAssembly( fullPathToAssembly );
Interface* pObject = NULL;
if (hDLL != NULL){
t_pCreateInstanceFunction pCreateInstanceFunction =
(t_pCreateInstanceFunction) ::GetProcAddress (hDLL, CREATE_INSTANCE_FUNCTION_NAME.c_str());
if ( pCreateInstanceFunction != NULL ){
//Yes, this assembly exposes the function we need
//Invoke the function to create the object
pObject = (*pCreateInstanceFunction)( marshal_as<string>(param) );
}
}
return pObject;
}
Run Code Online (Sandbox Code Playgroud)
(AssemblyLoader :: …
我在理解为什么 C++ 中需要 #include 和 LoadLibrary() 时遇到了一些麻烦。在 C++ 中,“#include”强制预处理器将 #include 行替换为您包含的文件的内容(通常是包含声明的头文件)。据我了解,这使我能够在标头所属的外部库中使用我可能想要的例程。
为什么我需要 LoadLibrary()?我不能只#include 库本身吗?
顺便提一下:在我更熟悉的 C# 中,如果我想在我的程序中使用来自该 DLL 的类型或例程,我只需添加对 DLL 的引用。我不必 #include 任何东西,因为 .NET 框架显然会自动搜索所有引用的程序集以查找我要使用的例程(由命名空间指定)
非常感谢您提前。
编辑:使用“定义”一词,但表示“声明”。现在固定了。
编辑 2:很难选择一个答案,很多很好的回复。感谢所有贡献。
帮助解释MSDN:
动态链接库搜索顺序
...
如果具有相同模块名称的DLL 已经在内存中加载,则系统在解析到已加载的DLL之前,仅检查重定向和清单,无论它位于哪个目录中。系统都不会搜索DLL。
注意:多个具有相同名称的DLL基本上不是一个好主意,这只是为了获得更好的画面。
考虑:
...\x\foo.exe
...\x\a\bar.dll ~ no further dependencies
...\x\b\bar.dll ~ no further dependencies
Run Code Online (Sandbox Code Playgroud)
是否可以通过显式加载库调用将这两个都加载bar.dll到foo.exe其中?以及在何处/如何记录和支持(否则,我会尝试一下。)
也就是说,以下各项是否可以在Windows7 +上可靠地工作:
// Load using full path:
HANDLE a_mod = LoadLibrary(L"...\x\a\bar.dll");
HANDLE b_mod = LoadLibrary(L"...\x\b\bar.dll");
// now use moth DLLs ...
Run Code Online (Sandbox Code Playgroud) 这是发生的事情:
然而:
到目前为止我尝试过的(没有成功):
系统信息:
关于可能发生什么的任何想法?
更新--更多信息和试验:
当尝试通过 LoadLibraryExW 加载 C:\Windows\System32\user32.dll 时,它失败并出现最后一个错误 ERROR_INVALID_IMAGE_HASH。
这是它的加载方式:
HMODULE User32Lib = LoadLibraryExW(L"C:\\Windows\\System32\\user32.dll", NULL, LOAD_LIBRARY_REQUIRE_SIGNED_TARGET);
Run Code Online (Sandbox Code Playgroud)
我查看了 DLL 本身,它是在 2020 年 4 月 8 日签署的(针对我机器上的版本),因此它应该仍然有效。
我做错了什么吗?
我在文档中没有找到这一点:如果我在程序结束之前需要 DLL 处理程序,我是否仍然应该FreeLibrary在调用程序结束之前调用,或者不需要?