.net WinDbg和SoS,如何打印/转储大字符串?

.net WinDbg和SoS,如何打印/转储大字符串?,.net,debugging,windbg,dump,sos,.net,Debugging,Windbg,Dump,Sos,我正在使用WinDbg和SoS扩展调试来自生产服务器的挂起转储 其中一个堆栈中有一个字符串参数,我需要知道它的值。但是,它是一个相当大的字符串,当我使用DumpObj时,WinDbg不会打印它。这是来自DumpObj的输出: 0:036> !do 00000001b30d8668 Name: System.String MethodTable: 0000064278436728 EEClass: 000006427803e520 Size: 5125300(0x4e34b4) bytes

我正在使用WinDbg和SoS扩展调试来自生产服务器的挂起转储

其中一个堆栈中有一个字符串参数,我需要知道它的值。但是,它是一个相当大的字符串,当我使用
DumpObj
时,WinDbg不会打印它。这是来自
DumpObj
的输出:

0:036> !do 00000001b30d8668
Name: System.String
MethodTable: 0000064278436728
EEClass: 000006427803e520
Size: 5125300(0x4e34b4) bytes
 (C:\WINDOWS\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: <String is invalid or too large to print>

Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000006427843d998  4000096        8         System.Int32  1 instance          2562638 m_arrayLength
000006427843d998  4000097        c         System.Int32  1 instance          2562637 m_stringLength
0000064278438170  4000098       10          System.Char  1 instance               3c m_firstChar
0000064278436728  4000099       20        System.String  0   shared           static Empty
                                 >> Domain:Value  0000000000163260:000000007fff0370 00000000001a6760:000000007fff0370 <<
0000064278438020  400009a       28        System.Char[]  0   shared           static WhitespaceChars
                                 >> Domain:Value  0000000000163260:000000007fff0b60 00000000001a6760:000000007fff89f0 <<
0:036>!请勿0000000 1B30D8668
名称:System.String
方法表:0000064278436728
EEClass:000006427803e520
大小:5125300(0x4e34b4)字节
(C:\WINDOWS\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
字符串:
领域:
MT字段偏移类型VT属性值名称
000006427843d998 4000096 8 System.Int32 1实例2562638 m_排列长度
000006427843d998 4000097 c System.Int32 1实例2562637米长
0000064278438170 4000098 10 System.Char 1实例3c m_firstChar
0000064278436728 4000099 20系统。字符串0共享静态空

>>域:Value 0000000000 163260:00000000 7FFF03700000000000 1A6760:00000000 7FFF0370>域:Value 0000000000 163260:00000000 7FFF0B60 0000000000 1A6760:00000000 7FFF89F0在转储2562638个字符的文本之前,我会三思而后行,但是如果您真的想,文本存储在字符串实例的字段后面,因此,您可以执行
du
来转储字符串的实际文本。输出将如下所示:

00000000`132ab050  "this is an extremely long string"
00000000`132ab090  " of text, so don't even bother t"
00000000`132ab0d0  "o try to dump it to the screen -"

通过将会话输出记录到文件中,您可以轻松捕获输出并执行所需的任何后处理

下面是我编写的脚本,用于将字符串转储到windbg中的文件中

$$ Dumps the managed strings to a file
$$ Platform x86
$$ Usage $$>a<"c:\temp\dumpstringtofolder.txt" 6544f9ac 5000 c:\temp\stringtest
$$ First argument is the string method table pointer
$$ Second argument is the Min size of the string that needs to be used filter
$$ the strings
$$ Third is the path of the file
.foreach ($string {!dumpheap -short -mt ${$arg1}  -min ${$arg2}})
{ 

  $$ MT        Field      Offset               Type  VT     Attr    Value Name
  $$ 65452978  40000ed        4         System.Int32  1 instance    71117 m_stringLength
  $$ 65451dc8  40000ee        8          System.Char  1 instance       3c m_firstChar
  $$ 6544f9ac  40000ef        8        System.String  0   shared   static Empty

  $$ start of string is stored in the 8th offset, which can be inferred from above
  $$ Size of the string which is stored in the 4th offset
  r@$t0=  poi(${$string}+4)*2
  .writemem ${$arg3}${$string}.txt ${$string}+8 ${$string}+8+@$t0
}
$$将托管字符串转储到文件中
$$平台x86

$$用法$$>aa如果您赶时间,请运行!在WinDbg中启用日志后执行。在日志文件中,您将获得整个字符串


在WinDbg菜单中,进入编辑->打开/关闭日志文件,以设置日志文件路径。

我已修改@Naveen的脚本以在x64平台上工作

伟大的脚本顺便说一句

$$ Dumps the managed strings to a file
$$ Platform x64
$$ Usage $$>a<"c:\temp\dumpstringtofolder.txt" 00007ffa6c509808 5000 c:\temp\stringtest
$$ First argument is the string method table pointer
$$ Second argument is the Min size of the string that needs to be used filter
$$ the strings
$$ Third is the path of the file
.foreach ($string {!dumpheap -short -mt ${$arg1}  -min ${$arg2}})
{ 
    $$               MT    Field   Offset                 Type VT     Attr            Value Name
    $$ 00007ffa6c50c158  400027b        8         System.Int32  1 instance               18 m_stringLength
    $$ 00007ffa6c50a9c0  400027c        c          System.Char  1 instance               53 m_firstChar
    $$ 00007ffa6c509808  4000280       c0        System.String  0   shared           static Empty

    $$ start of string is stored in the 8th offset, which can be inferred from above
    $$ Size of the string which is stored in the c-th offset
    r@$t0= (poi(${$string}+8) & 00000000FFFFFFFF) *2
    .writemem ${$arg3}${$string}.txt (${$string}+c) (${$string}+c+@$t0)
}
$$将托管字符串转储到文件中
$$平台x64

$$用法$$>aI无法让脚本为我工作,但基于您的示例,.writemem函数非常简单,我自己也能让它工作。@AndrewArnott我能够使用此脚本转储字符串,并且我经常使用它。你遇到了什么问题?您是否在x86/x64中使用它?不确定是否可以依赖的输出!Name2EE,但这可以用来自动获取方法表指针(r@$t1),因此我们可以去掉参数1。foreach/ps7/ps4(methodtable{!Name2EE mscorlib.dll System.String}){r@$t1=${methodtable}}@ThomasW。我同意。它可以使用
实现自动化!Name2EE
r@$t0=poi(${$string}+4)*2在这里*2完成了什么?
?如果字符串很长,由于限制,起始地址/结束地址语法将无法工作。你需要使用du L。对于非常长的字符串,这实际上会花费太长的时间,WinDbg不再响应。我在日志中得到的消息与在命令窗口中得到的消息相同:我在日志中得到的消息与在命令窗口中得到的消息相同:非常大的字符串似乎有问题。我得到字符串对象的输出,但是当我使用脚本时,它会在第三个0:000>处停止!转储堆-mt 00007ff8ca9d10b0-最小1000000地址mt大小000000670d17a4c8 00007ff8ca9d10b0 35377744 0000006717767bd8 00007ff8ca9d10b0 141515814 00000069686a1020 00007FF8CA9D10B0113213864000000068C06A1020 00007ff8ca9d10b0 566068092 00000069d06a1020 00007FF8D10B0 11321385888 mt统计计数TotalSize类名00007ff8ca9d10b0 5 3007238878系统。字符串Total 5对象我尝试修改WriteMem以使用长度范围而不是地址范围,但似乎也不起作用。writemem${$arg3}${$string}.txt(${$string}+c)L(@$t0)问题是它超过了256MB,需要L。writemem${$arg3}${$string}.txt(${$string}+c)L?(@$t0)