2016-06-03 5 views
1

Bitte beachten:Wie die Ausgabe von! Dumpheap in eine Datei ausgeben, wenn der Heap Millionen von Objekten enthält?

0:000> !dumpheap -stat 
Statistics: 
       MT Count TotalSize Class Name 
000007fefa9c8c58  1   24 System.ServiceProcess.Res 
000007fef99d3de8  1   24 System.Collections.Generic.GenericArraySortHelper`1[[System.DateTime, mscorlib]] 
000007fef99cf8e8  1   24 System.Collections.Generic.GenericComparer`1[[System.Decimal, mscorlib]] 
... 
000007fef8f02090 47295 141585288 System.Char[] 
000007fe9b1cbe20 1064155 229857480 Xyz.DataServices.Platform.BalanceTransactionForAccrualByOrg 
000007fef8f06888 21401 238104833 System.Byte[] 
000007fe9cd2efb8 1211503 358604888 Xyz.DataServices.Platform.AEBalanceTransaction 
0000000000386b30 11759620 1701611244  Free 
000007fef8e94918 777049 2352540408 System.Object[] 
000007fe9c4370e8 10571587 2621753576 Xyz.DB.DL.HREEmployeeManager 
000007fef8f00e08 131198125 1859306044 System.String 
Total 163792779 objects 
Fragmented blocks larger than 0.5 MB: 
      Addr  Size  Followed by 
... 

Was bedeutet, ich habe Dutzende von Millionen von Objekten auf dem Heap (Hunderte?). Ich möchte die Informationen über sie in eine Datei ablegen.

So sagt mir How to redirect windbg command to a file without echoing the output on the windbg console? den Ansatz, aber ist es das Beste, was wir bekommen können, wenn wir über Zehnen (Hunderte?) Von Millionen von Reihen sprechen?

Ich frage mich, ob es eine programmatische API gibt, gegen die ich programmieren könnte, um die Daten direkt aus dem Speicherauszug zu extrahieren, anstatt über die WinDBG-Benutzeroberfläche. Oder vielleicht gibt es ein Plugin da draußen, das macht es schon ...

+0

Related: http://StackOverflow.com/Questions/37624824, weil ich versucht habe, es für Sie zu implementieren –

+0

Sehr geschätzt. Ich weiß nicht, warum irgendjemand darüber abstimmen würde. – mark

+0

Ich frage mich auch manchmal über Downvotes. Ich habe wirklich versucht, es so minimal und vollständig wie möglich zu machen. Vielleicht denkt jemand, ich sollte die Müllkippe anhängen? –

Antwort

1

Am Ende des Tages habe ich ein Powershell-Skript geschrieben, um einen einzigen Debugger-Befehl mit CDB auszuführen. Dann wird die Ausgabe in der Datei gespeichert.

Hier ist sie:

param(
    [Parameter(Mandatory=$true, Position = 0)][ValidateScript({Test-Path $_ })] 
    $dump, 
    [Parameter(ParameterSetName='cmd', Mandatory=$true, Position = 1)][ValidateNotNullOrEmpty()] 
    $command, 
    [Parameter(ParameterSetName='script', Mandatory=$true)][ValidateNotNullOrEmpty()] 
    $scriptFile, 
    [Parameter(ParameterSetName='init', Mandatory=$true)][ValidateNotNullOrEmpty()][switch] 
    $init, 
    [Parameter()] 
    $imagePath, 
    [Parameter()] 
    $sosexPath = "e:\utils\sosex\64\sosex.dll", 
    [Parameter()][switch] 
    $ScanForImages, 
    [Parameter()][switch] 
    $NoSymbolServer, 
    [Parameter()][switch] 
    $NoExit 
) 
$dump = (dir $dump).FullName 

$cdb = "C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x64\cdb.exe" 
$InternalScriptFile = [io.path]::GetTempFileName() 
$log = [io.path]::GetTempFileName() 

if ($ScanForImages) 
{ 
    $ImgScan = ".imgscan /l" 
} 

Set-Content $InternalScriptFile @" 
.logopen `"${log}.init`" 
.load $sosexPath 
"@ 

if ($init) 
{ 
    $CDBOutputDevice = "Out-Default" 
    Add-Content $InternalScriptFile @" 
.logclose 
!bhi 
"@ 
} 
elseif ($command) 
{ 
    $CDBOutputDevice = "Out-Null" 
    Add-Content $InternalScriptFile @" 
!lhi 
$ImgScan 
.logclose 
.logopen `"${log}`" 
$command 
.logclose 
"@ 
} 
else 
{ 
    $CDBOutputDevice = "Out-Null" 
    Add-Content $InternalScriptFile @" 
!lhi 
$ImgScan 
.logclose 
.logopen `"${log}`" 
"@ 
    Get-Content $scriptFile | Out-File -FilePath $InternalScriptFile -Encoding ASCII -Append 
    Add-Content $InternalScriptFile @" 
.logclose 
"@ 
} 

if ($NoExit) 
{ 
    $CDBOutputDevice = "Out-Default" 
} 
else 
{ 
    Add-Content $InternalScriptFile @" 
q 
"@ 
} 

if ($NoSymbolServer) 
{ 
    $symbols = "e:\Symbols" 
} 
else 
{ 
    $symbols = "cache*e:\Symbols;srv*http://localhost:33417;srv*http://msdl.microsoft.com/download/symbols" 
} 
if (Test-Path $imagePath -PathType Container) 
{ 
    $symbols = "$imagePath;$symbols" 
} 

&$cdb -cf $InternalScriptFile -z $dump -y $symbols | &$CDBOutputDevice 
if (!$init -and !$NoExit) 
{ 
    cat $log 
} 

nicht ideal - Ich bin offen für Verbesserungen. Aber es funktioniert.