从Windbg中的ASP.net 3.5进程转储中检索会话内容

时间:2010-10-17 07:29:55

标签: asp.net session windbg

我已经转储了W3wp.exe进程并尝试使用Windbg检索会话内容。我的测试应用程序是在Windows 7 64位上运行的ASP.net 3.5,并且会话正在进行中。我可以检索各种其他对象的内容,但我很难找到会话内容的位置。

是的我知道在会话中存储内容很糟糕,但我需要这个来帮助在客户端站点调试问题。

我找到了Tess Ferrendez的一篇好文章(http://blogs.msdn.com/b/tess/archive/2007/09/18/debugging-script-dumping-out-asp-net-session-contents。 aspx),描述了创建一个脚本来迭代会话中的所有内容。

我怀疑这是针对以前版本的IIS(可能还有.net& 32bit),因为Tess的脚本会查找InProcSessionState对象,这些对象似乎不存在于我的转储中。

有关如何从转储中获取会话内容的任何想法吗?

谢谢,

亚历

1 个答案:

答案 0 :(得分:3)

此解决方案用于转储x64 asp.net会话对象。

以下是我用于将项目添加到会话的示例代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        this.Session.Add("Name", "Test");
        this.Session.Add("Name1", "Test1");
    }
}

以下是获取HttpSession对象内容的脚本

  .foreach ($obj {!dumpheap -mt ${$arg1} -short}) 
{
   $$ The !dumpheap -short option has last result as --------------- and 
   $$ this .if is to avoid this
   .if ($spat ("${$obj}","------------------------------")) 
     {} 
   .else 
     {
        $$ $t5 contains refernce to the array which has key and value for the
        $$ session contents

        r$t5 = poi(poi(poi(poi(${$obj}+0x8)+0x10)+0x8)+0x8);
         r$t1 = 0
        .for (r $t0=0; @$t0 < poi(@$t5+0x8); r$t0=@$t0+1 ) 
        {
          .if(@$t0 = 0) 
          { 
            $$ First occurence of the element in the array would be in the 20 offset
             r$t1=20
          }
          .else 
           { 
            $$ the rest of the elements would be in the 8th offset
            r$t1= 20+(@$t0*8)
           };

          $$ Check for null before trying to dump          

          .if (poi((@$t5-0x8)+@$t1) = 0 )
           {
              .continue
           } 
          .else
           {              
               .echo ************;
               ? @$t0
               $$ Session Key
               .printf "Session Key is :- "; !ds poi(poi((@$t5-0x8)+@$t1)+0x8);
               $$ Session value
               .printf "Session value is :- ";!ds poi(poi((@$t5-0x8)+@$t1)+0x10)
           }
        }
      }
}

将上述脚本复制到一个文件中,并在Windbg中调用此$$>a<"c:\temp\test.txt" 000007fef4115c20之类的脚本。将System.Web.SessionState.HttpSessionState的MT作为脚本参数传递。

这是脚本

的输出
************ 
Evaluate expression: 0 = 00000000`00000000 
Session Key is :- Name  
Session value is :- Test 
************ 
Evaluate expression: 1 = 00000000`00000001 
Session Key is :- Name1  
Session value is :- Test1

我使用别名!ds来转储字符串,而不是使用!dumpobj。要创建别名,请使用此命令as !ds .printf "%mu \n", 10+

除非你习惯编写windbg脚本,否则脚本有点神秘。

以下是脚本的简要说明

  1. $t5 - 包含对System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry
  2. 类型数组的引用
  3. 嵌套的.for循环将迭代数组项。如果您有兴趣了解custom dumparray
  4. ,我的博客也是如此
  5. 嵌套for循环.if中的.if (poi((@$t5-0x8)+@$t1) = 0)语句在使用!ds命令转储内容之前检查该项是否为空。
  6. !ds poi(poi((@$t5-0x8)+@$t1)+0x8) : - 会话的密钥字符串。示例Name
  7. !ds poi(poi((@$t5-0x8)+@$t1)+0x10): - 会话值。示例Test
  8. HTH

    编辑: - 这里还有一个独立于平台的脚本。这适用于x86和x64

    r $t9 = @$ptrsize;
    $$ $t8 register contains the next offset of the variable 
    $$ $t7 register contains array start address 
    .if (@$ptrsize = 8)
    { 
      r $t8 = 10
      r $t7 = 20
      r $t6 = 10
    } 
    .else 
    {
      r $t8 = 6
      r $t6 = 8
      r $t7 = 10
    }  
    .foreach ($obj {!dumpheap -mt ${$arg1} -short}) 
    {
       $$ The !dumpheap -short option has last result as --------------- and 
       $$ this .if is to avoid this
       .if ($spat ("${$obj}","------------------------------")) 
         {} 
       .else 
         {
            $$ $t5 contains refernce to the array which has key and value for the
            $$ session contents
    
             r$t5 = poi(poi(poi(poi(${$obj}+@$t9)+@$t6)+@$t9)+@$t9);
            .for (r $t0=0; @$t0 < poi(@$t5+@$t9); r$t0=@$t0+1 ) 
            {
              .if(@$t0 = 0) 
              { 
                $$ First occurence of the element in the array would be in the 20 offset
                 r$t1=@$t7
              }
              .else 
               { 
                $$ the rest of the elements would be in the 8th offset
                r$t1= @$t7+(@$t0*@$t9)
               };
              $$ Check for null before trying to dump          
              .if (poi((@$t5-@$t9)+@$t1) = 0 )
               {
                  .continue
               } 
              .else
               {              
                   .echo ************;
                   ? @$t0
                   $$ Session Key
                   .printf "Session Key is :- "; !ds poi(poi((@$t5-@$t9)+@$t1)+@$t9);
                   $$ Session value
                   .printf "Session value is :- ";!ds poi(poi((@$t5-@$t9)+@$t1)+@$t6)
               }
            }
          }
    }