18. Januar 2009

.NET Dumps mit WinDbg analysieren

Mit WinDbg (Teil der Windows Debugging Tools) kann man auch .NET Dumps analysieren. Dazu muss es am besten mit der "Visual Studio Eingabeaufforderung" gestartet werden (so sind alle notwendigen Pfade automatisch gesetzt.

Dort kann einen zuvor mit adplus erstellten Dump laden.

Zunächst muss die Managed-Unterstützung geladen werden über die WinDbg-Kommadozeile
.loadby sos mscorwks
Eventuell fehlen hier Symbole. Sollte das der Fall sein, dann einfach im Menü File->Symbol Path auswählen und dort zusätzlich
http://msdl.microsoft.com/download/symbols
eintragen, dann werden die benötigten Symbole einfach von Microsoft heruntergeladen.


Sollte das System, auf dem der Dump gemacht wurde und das System, auf dem der Dump analysiert werden soll sich in der .NET Framework Version (auch nur minimal) unterscheiden, so muss die Datei mscordacwks.dll des gedumpten Systems in den Symbol-Pfad mit dem Namen
mscordacwks_<arch>_<arch>_<version>.dll
aufgenommen werden. (Siehe auch http://blogs.msdn.com/b/tom/archive/2008/04/09/asp-net-tips-getting-sos-to-work-when-commands-fail.aspx)


Heap analysieren
!DumpHeap
liefert z.B.: folgende Ausgabe:
MT    Count    TotalSize Class Name
6ef5fba8       73         4088 System.Reflection.RuntimeMethodInfo
68634fb4       28         4144 System.Data.DataColumn
68df1488       61         4392 System.Windows.Forms.PropertyStore+ObjectEntry[]
6ef60508      392         4704 System.Object
6ef62f40       92         5152 System.Collections.Hashtable
68635d88        5         5180 System.Data.RBTree`1+Node[[System.Data.DataRow, System.Data]][]
6b5f8c4c       95         5320 System.Configuration.FactoryRecord
6ef62a88       89         5576 System.Int32[]
6ef4c47c      230         6440 System.Security.SecurityElement
6ef61a6c      369         7380 System.RuntimeType
6ef6151c       81         9880 System.Char[]
68636e00       10        10360 System.Data.RBTree`1+Node[[System.Int32, mscorlib]][]
6ef6335c       79        17652 System.Byte[]
6ef6303c       93        21240 System.Collections.Hashtable+bucket[]
6ef62b38     4643        55716 System.Int32
68636f00     2311        64708 System.Data.RBTree`1+RBTreeEnumerator[[System.Data.DataRow, System.Data]]
6ef340bc      627        75216 System.Object[]
6ef5a930     2328        83808 System.Collections.Hashtable+HashtableEnumerator
68df5158     9246       110952 System.Windows.Forms.Control+MultithreadSafeCallScope
6ef6291c     5017       120408 System.Collections.ArrayList
6ef62c14     4622       129416 System.Collections.ArrayList+ArrayListEnumeratorSimple
6ef60a28    11593       231860 System.Text.StringBuilder
6ef608ec    18367      1163300 System.String


Dump aller Objekte im LargeObjectHeap
!dumpheap -min 85000



Threadstack analysieren
Liste der CLR Threads
!threads
anzegen:
PreEmptive   GC Alloc           Lock
ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
0    1 10c4 0026a4f0      6020 Enabled  0211b030:0211ca74 00266280     0 STA
2    2 1124 002779c0      b220 Enabled  00000000:00000000 00266280     0 MTA (Finalizer)
3    3 1360 002f4078   880b220 Enabled  00000000:00000000 00266280     0 MTA (Threadpool Completion Port)
4    4 1368 002f6d58    80a220 Enabled  00000000:00000000 00266280     0 MTA (Threadpool Completion Port)


Dort wählt man sich den gewünschten Thread aus über
~<ID>s
, also um den Thread mit der ID 0 anzuschauen gibt man
~0s
ein. Dann kann man sich mit
!CLRStack
nur Managed Stack ausgeben lassen, was z.B. zu folgender Ausgaben führt:
SharpShutdown+0x1632e (012f632e)
Priority: 0  Priority class: 32  Affinity: 3
0:000> !clrstack -p
OS Thread Id: 0x10c4 (0)
ESP       EIP
0016f240 775a9a94 [InlinedCallFrame: 0016f240] System.Windows.Forms.UnsafeNativeMethods.WaitMessage()
0016f23c 68da8e48 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
PARAMETERS:
this = 0x01f68694
dwComponentID = 
reason = 0xffffffff
pvLoopData = 0x00000000

0016f2d8 68da8937 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
PARAMETERS:
this = 0x01f3ef78
reason = 0xffffffff
context = 0x01f634b8

0016f32c 68da8781 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
PARAMETERS:
this = 
reason = 
context = 

0016f35c 68d65911 System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
PARAMETERS:
mainForm = 

0016f370 00eac769 DE.RFeest.Tools.SharpShutdown.Program.Main()

CPU-Zeit der einzelnen Threads
!runaway
User Mode Time
Thread       Time
12:1818      0 days 0:02:46.359
25:1164      0 days 0:02:42.859
31:1d54      0 days 0:01:05.421
33:140c      0 days 0:01:03.031
34:794       0 days 0:00:55.562
30:120c      0 days 0:00:53.031
32:1980      0 days 0:00:49.937
37:1900      0 days 0:00:42.640
38:1dc8      0 days 0:00:41.984
17:1da0      0 days 0:00:35.156
14:1bb0      0 days 0:00:34.937
15:1848      0 days 0:00:34.546
16:8fc       0 days 0:00:34.109
39:1398      0 days 0:00:29.140
35:7f4       0 days 0:00:27.015
40:1270      0 days 0:00:26.625
36:1908      0 days 0:00:17.781
Details zu einer Managed-Exeception
29   18 1458 2039df38   180b220 Enabled  0e15d56c:0e15d57c 00109f58     3 MTA (Threadpool Worker) System.OutOfMemoryException (05c6c578)
kann man sich über
!pe
anzeigen lassen:
Exception object: 126449bc
Exception type: System.OutOfMemoryException
Message: 
InnerException: 
StackTrace (generated):
SP       IP       Function
7C7EE5A4 792F110C mscorlib_ni!System.Reflection.Assembly.nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.Assembly, System.Threading.StackCrawlMark ByRef, Boolean, Boolean)+0x2c
7C7EE5CC 792D5B58 mscorlib_ni!System.Reflection.Assembly.InternalGetSatelliteAssembly(System.Globalization.CultureInfo, System.Version, Boolean)+0xd8
7C7EE5F0 792D4000 mscorlib_ni!System.Resources.ResourceManager.GetSatelliteAssembly(System.Globalization.CultureInfo)+0x50
7C7EE61C 792821AC mscorlib_ni!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo, Boolean, Boolean)+0x12c
7C7EE670 792822C8 mscorlib_ni!System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo, Boolean, Boolean)+0x248
7C7EE6C4 7928190B mscorlib_ni!System.Resources.ResourceManager.GetString(System.String, System.Globalization.CultureInfo)+0x4b
7C7EE6E4 6522C3ED System_Data_ni!System.Data.Res.GetString(System.String)+0x1d
7C7EE6F0 654CD912 System_Data_ni!System.Data.Common.ADP.PooledOpenTimeout()+0x12
7C7EE700 656C70B4 System_Data_ni!System.Data.ProviderBase.DbConnectionFactory.GetConnection(System.Data.Common.DbConnection)+0x4a36e4
7C7EE720 65223846 System_Data_ni!System.Data.ProviderBase.DbConnectionClosed.OpenConnection(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory)+0x76
7C7EE754 6521DF06 System_Data_ni!System.Data.SqlClient.SqlConnection.Open()+0xf6
...
StackTraceString: 
HResult: 8007000e
Anaylse von aufgezeichneten Exceptions Wenn folgendes von windbg ausgegeben wird:
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
kann man eine Analyse dieser Exception ausführen:
!analyze -v
Siehe auch: http://msdn.microsoft.com/en-us/magazine/cc163528.aspx http://www.informit.com/articles/article.aspx?p=1409801&seqNum=4 http://msdn.microsoft.com/en-us/library/bb190764.aspx http://blogs.msdn.com/b/alejacma/archive/2009/08/13/managed-debugging-with-windbg-managed-heap-part-1.aspx http://www.zhaun.net/post/Debugging-NET-virtual-memory-fragmentation-with-WinDbg.aspx http://www.codeproject.com/KB/dotnet/BestPractices5.aspx#WhatisthetypeofmemoryleakTotalMemoryManagedmemoryunmanagedmemory

Dumps mit dem .NET Framework erstellen

Mit ADPlus (Teil der Windows Debug Tools) kann man Dumps (enthält u.a. HeapDump und ThreadDump) eines laufenden Prozesses machen:

Dump eines Prozessed mit einer speziellen ID
adplus -Hang -o . -p 3720
Dump aller Prozesse mit einem speziellen Namen (hier die IIS Prozesse)
adplus -Hang -o . -pn w3wp.exe
Der Dump kann dann mit WinDbg (ebenfalls Teil der Windows Debug Tools) oder einem kommerziellen Tool wie MemProfiler analysiert werden.

16. Januar 2009

Mehr als 4GB mit 32Bit Windows

Unter Windows (z.B. mit Windows 2003 Enterprise Edition) kann mehr als 4GB adressiert werden. Auch mit der 32 Bit Variante. Das Stichwort lautet hier /pae (Physical Address Extension). Wichtig: PAE ermöglicht nur in Summe (der Prozesse) über die 4GB zu kommen, nicht pro Prozess - 1 Prozess mit 10GB, also z.B. 10 Prozesse mit 1 GB). Dazu ist aber keine Codeänderung notwendig.

Unter diesen Links finden sich mehr Informationen zu PAE:
PAE 1
PAE 2

Genaue Systeminfo unter Windows

Mit dem Befehl
systeminfo
kann man sich genaue Infos über das Window-System geben lassen (z.B. Anzahl der Prozessoren, 32 oder 64bit Prozessor, Bios-Version, etc.

13. Januar 2009

DDLs generieren mit DB2

Mit dem Tool db2look (z.B. bei Windows IBM\Sqllib\BIN\db2look.exe) können DDLs generiert werden. Am besten direkt auf dem DBServer ausführen.

db2look -d [dbname] -i [dbuser] -w [password] -o myfile.ddl -e -z [schema]

Variablen:
[dbname] : Datenbank, zu der man sich verbinden will
[dbuser] : DB-Benutzer
[password] : Password des DB-Benutzers
[schema] : Schema, das exportiert werden soll

5. Januar 2009

Kein MMC-Plugin für .NET Framework 3.0 / 3.5

Problem: Es gibt zwar die Ordner
C:\Windows\Microsoft.NET\Framework\v3.5
und
C:\Windows\Microsoft.NET\Framework\v3.0
Dort ist aber keine Konfigurationsdatei machine.config. Genauso fehlt das MMC-Plugin

Lösung: Weder .Net 3.0 noch 3.5 sind Stand-Alone-Versionen. Beide benötigen das .NET Framework 2.0. Konfiguartionen müssen also über die 2.0-Infrastruktur abgehandelt werden.

4. Januar 2009

ASP.NET Control führt in der VisualStudio-Entwurfsansicht zu Fehler

Problem: In einem ASP.NET Projekt wird versucht in der Designansicht ein Control auf ein WebForm zu ziehen. Das ist nicht möglich. Über die Quellansicht läßt sich das Control zwar hinzufügen, in der Design Ansicht erhält man jedoch folgende Fehlermeldung
Fehler beim Erstellen des Steuerelements... Webprojektelement "... " kann nicht gefunden werden.


Ursache: Der Designer scheint Probleme mit Sonderzeichen wie dem # (Sharp) zu haben. Kommt so ein Sonderzeichen im Pfad zur aspx.-Datei vor führt es zu dem oben beschriebenen Fehler.

Lösung: Die Sonderzeichen aus dem Pfad weglassen. Leider gibt´s wohl keine andere Möglichkeit.