如何以编程方式获取DLL依赖项

如何以编程方式获取DLL依赖项,dll,dependencies,Dll,Dependencies,如何获取给定DLL或EXE文件的所有DLL依赖项的列表 换言之,我希望与“Dependency walker”工具一样,但要以编程方式 Windows(理想情况下是.NET)的API是什么?您可以使用函数。kaanbardak建议的托管API不会提供本机模块的列表 例如,请参见MSDN上的 如果需要静态分析dll,则必须深入了解导入表。请参阅此以了解详细信息 注意:根据下面帖子的评论,我想这可能也会遗漏非托管依赖项,因为它依赖于反射 下面是Jon Skeet在bytes.com上编写的一个小型c

如何获取给定DLL或EXE文件的所有DLL依赖项的列表

换言之,我希望与“Dependency walker”工具一样,但要以编程方式

Windows(理想情况下是.NET)的API是什么?

您可以使用函数。kaanbardak建议的托管API不会提供本机模块的列表

例如,请参见MSDN上的

如果需要静态分析dll,则必须深入了解导入表。请参阅此以了解详细信息

注意:根据下面帖子的评论,我想这可能也会遗漏非托管依赖项,因为它依赖于反射

下面是Jon Skeet在bytes.com上编写的一个小型c#程序

使用系统;
运用系统反思;
使用系统集合;
公共类从属报告程序
{
静态void Main(字符串[]参数)
{
//如果只需要运行代码1,请更改此行:
字符串dllToCheck=@“”;
尝试
{
如果(args.Length==0)
{
如果(!String.IsNullOrEmpty(dllToCheck))
{
args=新字符串[]{dllToCheck};
}
其他的
{
控制台写入线
(“用法:DependencyReporter[assembly2…]);
}
}
Hashtable alreadyLoaded=新Hashtable();
foreach(参数中的字符串名称)
{
Assembly assm=Assembly.LoadFrom(名称);
转储程序集(assm,alreadyLoaded,0);
}
}
捕获(例外e)
{
错误(e);
}
Console.WriteLine(“\n按任意键继续…”);
Console.ReadKey();
}
静态无效转储程序集(程序集assm、哈希表ALREADYLADED、整数缩进)
{
Write(新字符串(“”,缩进));
AssemblyName fqn=assm.GetName();
if(alreadyLoaded.Contains(fqn.FullName))
{
WriteLine(“[{0}:{1}]”,fqn.Name,fqn.Version);
返回;
}
alreadyLoaded[fqn.FullName]=fqn.FullName;
Console.WriteLine(fqn.Name+“:”+fqn.Version);
foreach(assm.GetReferencedAssemblys()中的AssemblyName名称)
{
尝试
{
引用的程序集=程序集.Load(名称);
转储程序集(引用,已添加,缩进+2);
}
捕获(例外e)
{
错误(e);
}
}
}
静态无效转储错误(异常e)
{
Console.ForegroundColor=ConsoleColor.Red;
WriteLine(“错误:{0}”,e.Message);
Console.WriteLine();
Console.ResetColor();
}
}

要获取本机模块依赖项,我认为从PE文件的导入表中获取本机模块依赖项应该是可以的,这里有两个链接详细解释了这一点:

要获取.NET依赖项,我们可以使用.NET的API,如Assembly.Load

若要获取.NET模块的所有依赖项,请将这两种方式结合起来-.NET程序集仅为PE文件和元数据。

若要读取运行的exe加载的DLL(模块),请使用ToolHelp32函数


不确定运行exe的.Net会显示什么(我从未尝试过)。但是,它确实显示了加载DLL的完整路径。通常,这是我在试图解决DLL问题时需要的信息。Net应该已经消除了使用这些函数的需要(有关更多信息,请查阅DLL地狱)。

虽然这个问题已经有了一个公认的答案,但其他答案中引用的文档(未损坏的地方)是旧的。我的方法是这样的,而不是通读所有内容后才发现它没有涵盖Win32和x64之间的差异或其他差异:

C:\UnxUtils\usr\local\wbin>strings.exe E:\the-directory-I-wanted-the-info-from\*.dll > E:\TEMP\dll_strings.txt
这使我可以使用记事本++或gvim或其他任何工具来搜索仍然依赖于dll名称末尾带有120.dll的MS dll的dll,以便找到需要更新的dll

这可以很容易地用您最喜欢的语言编写脚本


考虑到我对该信息的搜索考虑的是VS 2015,而这个问题是Google搜索的最高结果,我提供的答案是,它可能对其他寻找相同信息的人有用。

如果您不想在程序中加载程序集,可以使用DnSpy():


请注意,您在“ManifestModule”属性中拥有所需的所有信息。

如果您想在不加载dll的情况下分析dll,则需要阅读其导入表断开的教程链接(?)快速链接到优秀教程在回程机中的最后一项:此代码不会显示非托管模块。Cecil对于托管代码来说是一个更好的解决方案,因为它不需要您将程序集加载到AppDomain中(以后也不能卸载程序集)。它添加了额外的try/catch,如果一个程序集失败,则应列出其他程序集。为异常添加了一种颜色和一个回车符,以便更容易阅读。当您只想运行F5进行快速概览时,添加了一个字符串字段(比将其添加到生成设置中更容易)。
var assemblyDef = dnlib.DotNet.AssemblyDef.Load("yourDllName.dll");
var dependencies = assemblyDef.ManifestModule.GetAssemblyRefs();