【发布时间】:2017-07-31 16:27:43
【问题描述】:
我需要以编程方式获取 DLL 的依赖项列表。以下是我尝试解决此任务的方法:
BSTR GetDllDependencies(const wchar_t* dllPath)
{
std::wstring dependencies;
struct LibDeleter
{
typedef HMODULE pointer;
void operator()(HMODULE hMod) { FreeLibrary(hMod); }
};
auto hModRaw = LoadLibraryExW(dllPath, NULL, DONT_RESOLVE_DLL_REFERENCES); //(*)nullptr nere
auto hMod = std::unique_ptr<HMODULE, LibDeleter>();
auto imageBase = (DWORD_PTR)hMod.get();
auto header = ImageNtHeader(hMod.get());
auto importRVA = header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
auto importTable = (PIMAGE_IMPORT_DESCRIPTOR)(DWORD_PTR)(importRVA + imageBase);
while (importRVA && importTable->OriginalFirstThunk)
{
auto importedModuleName = (char*)(DWORD_PTR)(importTable->Name + imageBase);
dependencies
.append(importedModuleName, importedModuleName + std::strlen(importedModuleName))
.append(L",");
importTable++;
}
auto result = SysAllocString(dependencies.c_str());
return result;
}
它有效。但是,如您所见,它将 DLL 加载到进程中。我在这个地方遇到了一个问题:如果进程已经加载了同名的 DLL,LoadLibraryEx 返回nullptr。
我不确定是否允许将两个同名(但位置不同)的 DLL 加载到同一个进程中?我相信是的。那为什么LoadLibraryEx 返回nullptr?是否有可能在不加载 DLL 的情况下以某种方式获取 DLL 依赖项?
【问题讨论】:
-
您需要解析PE(Portable Executable)文件(即.dll或.exe)的导入部分。
-
正如文档
DONT_RESOLVE_DLL_REFERENCESis deprecated and may not be supported in all versions of windows 中提到的,您需要将其作为数据文件加载。 -
LoadLibraryEx returns nullptr if process already has loaded DLL with the same name这不是真的 -
Then why LoadLibraryEx returns nullptr- 那你为什么不打电话给GetLastError或RtlGetLastNtStatus呢?
标签: c++ dll portable-executable loadlibrary systems-programming