Debugging 如何在windbg中识别托管dll的版本?
我从一个顾客那里得到一个小垃圾桶。我想找出加载的.NET DLL的程序集版本。我已经在网上搜索了好几个小时了,但是找不到一个有用的方法。 我有windbg并加载了SOS扩展,我有必要的clr.dll和mscordacwksDebugging 如何在windbg中识别托管dll的版本?,debugging,dll,windbg,unmanaged,Debugging,Dll,Windbg,Unmanaged,我从一个顾客那里得到一个小垃圾桶。我想找出加载的.NET DLL的程序集版本。我已经在网上搜索了好几个小时了,但是找不到一个有用的方法。 我有windbg并加载了SOS扩展,我有必要的clr.dll和mscordacwks 使用lm-v仅显示非托管dll。我确信我忽略了一些非常简单的事情。好吧,经过进一步的研究,我得出结论,这种信息不适用于小型转储中的dll。无论如何,我至少能够获得更多关于这些文件的信息,也许这对将来的其他人有用 您至少可以获得dll的metata信息,也许您可以在其中找到有用
使用
lm-v
仅显示非托管dll。我确信我忽略了一些非常简单的事情。好吧,经过进一步的研究,我得出结论,这种信息不适用于小型转储中的dll。无论如何,我至少能够获得更多关于这些文件的信息,也许这对将来的其他人有用
您至少可以获得dll的metata信息,也许您可以在其中找到有用的东西。以下是如何做到这一点:
首先获取域:
!dumpdomain
最终可能会出现大量列出的程序集。现在,您可以使用以下工具手动查找它们:
!dumpassembly ADDRESS
或者,您也可以使用懒惰的方式:安装windbg()的python扩展,并使用以下脚本进行快速忽略(这可能不是最好的脚本,但它正在工作,我不想投入更多时间):
现在可以对dll进行文本搜索(CTRL+F)。一旦找到它,就可以在模块名称旁边找到偏移量(看起来像12327C8 C:\Program Files\MyApp\MyDLL.dll)
现在,您可以使用以下方法转储模块:
!dumpmodule 12327C8
这将导致您:
Name: C:\Program Files\MyApp\MyDLL.dll
Attributes: PEFile
Assembly: 131a22e2
LoaderHeap: 00000000
TypeDefToMethodTableMap: 19220010
TypeRefToMethodTableMap: 134303e0
MethodDefToDescMap: 13430740
FieldDefToDescMap: 13433964
MemberRefToDescMap: 134350c8
FileReferencesMap: 13435918
AssemblyReferencesMap: 1343591c
MetaData start address: 1c1aaa4c (4248 bytes)
现在,您只需使用以下命令即可检查dll的元数据:
dc 1c1aaa4c 1c1aaa4c + 4248
这是我能得到的最接近DLL的更多信息。不幸的是,文件版本没有写在那里,只是一些其他更通用的信息。不管怎样,我会尝试再次与客户联系。无论如何,感谢您的回答。WinDbg的
lm v
显示所有DLL,包括托管和非托管。在这个级别上,程序集只是一个DLL,只是一个模块
在WinDbg 6.3.9600中,lm v
甚至显示模块是否具有CLR头的信息:
0:008> lmv m MyApp
start end module name
10310000 10574000 MyApp(deferred)
Image path: C:\...\MyApp.exe
Image name: MyApp.exe
Has CLR image header, track-debug-data flag not set
Timestamp: Wed May 21 16:34:02 2014 (537CB95A)
...
ProductVersion: 1.8.0.44
FileVersion: 1.8.0.44
...
但是,FileVersion和ProductVersion仍然是编译到DLL的本机资源部分的非托管信息
我建议您使用!SaveModule
将文件保存在磁盘上,然后使用反射工具(如打开文件)从中获取程序集信息,这将为您提供名称、版本、区域性和公钥令牌
要保存所有模块,请执行以下操作:
!for_each_module .if ($spat ("${@#ImageName}","*.exe")) { !SaveModule ${@#Base} c:\temp\${@#ModuleName}.exe } .else { !SaveModule ${@#Base} c:\temp\${@#ModuleName}.dll }
它嵌入在程序集的非托管资源(版本资源)中。“minidump”中的mini通常会阻止它进入您的机器,minidump的设计并不能很好地处理托管代码。没有包含完整的GC堆是另一个典型的障碍。只需向客户索要一份副本,或者读回您关于dialog的Help+。minidump这个术语非常不幸。根据给定的选项,它可能比完全转储更完整。一般来说,对于托管应用程序/ma是理想的。您可以使用| |命令检查转储的类型。类型显示为“用户迷你转储”,工作起来很有魅力。这就是我想要多投一票的地方!!SaveModule为我工作,我能够从属性对话框详细信息选项卡中获取版本。元数据大小以十进制指定,因此您应该开始编写0n4248:
dc 1c1aaa4c 1c1aaa4c+0n4248
。否则,您将很难找到版本号。我无法编辑答案
!for_each_module .if ($spat ("${@#ImageName}","*.exe")) { !SaveModule ${@#Base} c:\temp\${@#ModuleName}.exe } .else { !SaveModule ${@#Base} c:\temp\${@#ModuleName}.dll }