Generate Dumps Using DebugDiag and Perfmon Counters - Control Script Samples
Sample 1: DbgSVC.Memory.Trigger
Features:
- Inject leaktrack.dll into all current and new w3wp.exe instances
- Dump w3wp.exe when its 'Virtual Bytes' counter reaches 1.8 GB.
- Multiple varying triggers for a single process.
Sample 2: PerfTriggerSample
Features:
- Dump w3wp.exe when the 'Request Execution Time' counter for the 'ASP.NET' perfmon object reaches 80 seconds.
Setup for both samples:
- Backup - rename "C:\Program Files\IIS Resources\DebugDiag\Scripts\DbgSVC.vbs" to: "DbgSVC.original"
- Update - copy/paste the code from the appropriate sample code listing below into the original DbgSVC.vbs file.
- Modify the contents of this new DbgSVC.vbs file in notepad as needed to fit your scenario - i.e. change/add any of the following items in the scripts:
- process names
- perfmon counter names
- perfmon counter thresholds
- actions to be taken when thresholds are reached
- (see notes at the top of the sample code for which line numbers to change)
- Restart the "Debug Diagnostic Service"
Note: These scripts do not have a "Maximum Userdump Limit" like a ypical crash/hang rule does. While this script is in place and the DebugDiag service is running it will continue to create DMP's for each process that exceeds the trigger threshold. To disable this script, replace the original then restart the DebuDiag service again.
Sample Code Listings
Note both samples are also available in the attached DebugDiagPerfTriggerSamples.zip file.
DbgSVC.vbs code for Sample 1: DbgSVC.Memory.Trigger
' Note make modifications to processes/counters/thresholds near line 107.
' Note make modifications to the actions taken beginning at line 466.
Const SymbolPath = "SRV*C:\symbols*https://msdl.microsoft.com/download/symbols"
Set ServiceState = Controller.ServiceState
Set HTTPPinger = Controller.HTTPPinger
Set triggers = New TriggerItems
Sub WriteToLog(ByVal Output)
Controller.Write "[" & Now() & "] "
Controller.Write Output & vbCRLF
End Sub
Function FormatString(ByVal InputString, ByVal FieldLength)
FormatString = InputString
If Len(InputString) < FieldLength Then
FormatString = FormatString & Space(FieldLength - Len(InputString))
End If
End Function
Sub Controller_OnStart()
Dim NewTrigger
WriteToLog "DbgSvc started"
CreatePingURLs
End Sub
Sub Controller_OnPerfTriggerHit(ActiveTrigger)
triggers.Triggered ActiveTrigger
End Sub
Sub Controller_OnShutdown()
WriteToLog "DbgSVC stopped"
End Sub
Sub HandleProcess(ByVal Process, ByVal ControlScript)
If Process.IsDebuggerAttached Then
WriteToLog FormatString("Reload Control Script:",25) & " Process Name - " & FormatString(Process.ProcessName,20) & _
" Process ID - " & FormatString(Process.ProcessID, 6) & " Control Script - " & ControlScript
Process.ReloadControlScript ControlScript
ElseIf Not Process.IsBeingDebugged Then
WriteToLog FormatString("Attach Debugger:",25) & " Process Name - " & FormatString(Process.ProcessName,20) & _
" Process ID - " & FormatString(Process.ProcessID, 6) & " Control Script - " & ControlScript
Process.AttachToProcess ControlScript, SymbolPath, ""
Else
WriteToLog FormatString("Unknown Debugger:",25) & " Process Name - " & FormatString(Process.ProcessName,20) & _
" Process ID - " & FormatString(Process.ProcessID, 6)
End If
End Sub
Sub HandleService(ByVal Service)
If Service.ProcessID <> 0 and Service.CurrentState = "SERVICE_RUNNING" Then
ControlScript = GetControlScriptForService(Service)
If ControlScript <> "" Then
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(Service.ProcessID)
If Not Process Is Nothing Then
HandleProcess Process, ControlScript
End If
End If
End If
End Sub
Sub Controller_OnNewServiceFound(ByVal NewService)
WriteToLog FormatString("New service found:",25) & " Service Name - " & FormatString(NewService.ServiceName, 20) & _
" Process ID - " & FormatString(NewService.ProcessID, 6) & " Current State - " & NewService.CurrentState
HandleService NewService
End Sub
Sub Controller_OnServiceStateChanged(ByVal AffectedService)
WriteToLog FormatString("Service state changed:",25) & " Service Name - " & FormatString(AffectedService.ServiceName,20) & _
" Process ID - " & FormatString(AffectedService.ProcessID, 6) & " Current State - " & AffectedService.CurrentState
HandleService AffectedService
End Sub
Sub Controller_OnNewProcessFound(ByVal NewProcess)
Dim Message
Dim GFlags
Message = FormatString("New process found:",25) & " Process Name - " & FormatString(NewProcess.ProcessName,20) & _
" Process ID - " & FormatString(NewProcess.ProcessID, 6) & " Process Identity - " & FormatString(NewProcess.ProcessIdentity, 40)
GFlags = Controller.GetGlobalFlagForProcess(NewProcess.ProcessName)
If GFlags <> "" Then
Message = Message & " Global Flags - " & FormatString(GFlags, 12)
End If
If NewProcess.COMPlusPackageName <> "" Then
Message = Message & " MTS/COM+ package name - " & NewProcess.COMPlusPackageName
ElseIf NewProcess.WebAppPoolName <> "" Then
Message = Message & " Web application pool name - " & NewProcess.WebAppPoolName
End If
WriteToLog Message
Select Case UCase(NewProcess.ProcessName)
Case "W3WP.EXE":
'triggers.Add <ProcessObject>, <InjectLeakTrack>, <Perfmon Counter Path>, <Trigger Threshold>
'triggers.Add NewProcess, True, "\Process({0})\Virtual Bytes", 1024*1024*800 ' (800 MB)
'triggers.Add NewProcess, True, "\Process({0})\Virtual Bytes", 1024*1024*1024*1.3 ' (1.3 GB)
triggers.Add NewProcess, True, "\Process({0})\Virtual Bytes", 1024*1024*1024*1.8 ' (1.8 GB)
'triggers.Add NewProcess, True, "\Process({0})\Working Set", 1024*1024*400 ' (400 MB)
'triggers.Add NewProcess, True, "\Process({0})\Working Set", 1024*1024*600 ' (600 MB)
'triggers.Add NewProcess, True, "\Process({0})\Working Set", 1024*1024*800 ' (800 MB)
End Select
ControlScript = GetControlScriptForProcess(NewProcess)
If ControlScript <> "" Then HandleProcess NewProcess, ControlScript
End Sub
Sub Controller_OnProcessExited(ByVal ExitingProcess)
Dim Message
Message = FormatString("Process Exited:",25) & " Process Name - " & FormatString(ExitingProcess.ProcessName,20) & _
" Process ID - " & FormatString(ExitingProcess.ProcessID, 6)
If ExitingProcess.COMPlusPackageName <> "" Then
Message = Message & " MTS/COM+ package name - " & ExitingProcess.COMPlusPackageName
ElseIf ExitingProcess.WebAppPoolName <> "" Then
Message = Message & " Web application pool name - " & ExitingProcess.WebAppPoolName
End If
WriteToLog Message
triggers.Remove ExitingProcess
End Sub
Sub StartLeakRule(ByVal ProcessID)
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(ProcessID)
If Process Is Nothing Then
WriteToLog FormatString("Start Leak Rule Failed:",25) & " Process ID - " & _
FormatString(ProcessID, 6) & " Process Not Found"
Else
Process.InjectLeakTrack
WriteToLog FormatString("Leak Rule Started:",25) & " Process ID - " & _
FormatString(ProcessID, 6)
End If
End Sub
Sub StopLeakRule(ByVal ProcessID, ByVal RuleFolder, ByVal bUnloadLeakTrack)
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(ProcessID)
If Process Is Nothing Then
WriteToLog FormatString("Stop Leak Rule Failed:",25) & " Process ID - " & _
FormatString(ProcessID, 6) & " Process Not Found"
Else
DumpPath = Process.CreateDump("Leak Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(ProcessID, 6) & " Dump Path - " & DumpPath
If bUnloadLeakTrack Then
Process.UnloadLeakTrack
WriteToLog FormatString("Leak Rule Stopped:",25) & " Process ID - " & _
FormatString(ProcessID, 6)
End If
End If
End Sub
Sub DumpAllIISProcesses(ByVal RuleFolder)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
ProcessName = UCase(Process.ProcessName)
Select Case ProcessName
Case "INETINFO.EXE", "MTX.EXE", "DLLHOST.EXE", "DLLHST3G.EXE", "W3WP.EXE", "ASPNET_WP.EXE"
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End Select
Next
End Sub
Sub DumpProcess(ByVal RuleFolder, ByVal TargetName)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
ProcessName = UCase(Process.ProcessName)
If ProcessName = UCase(TargetName) Then
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End If
Next
End Sub
Sub DumpCOMPlusApp(ByVal RuleFolder, ByVal TargetName)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
PackageName = UCase(Process.COMPlusPackageName)
If PackageName = UCase(TargetName) Then
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End If
Next
End Sub
Sub DumpWebAppPool(ByVal RuleFolder, ByVal TargetName)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
AppPoolName = UCase(Process.WebAppPoolName)
If AppPoolName = UCase(TargetName) Then
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End If
Next
End Sub
Sub DumpProcessID(ByVal RuleFolder, ByVal TargetPID)
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(TargetID)
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End Sub
Sub DumpNTService(ByVal RuleFolder, ByVal TargetName)
Set ServiceManager = Controller.Processes
For each NTService in ServiceManager
ServiceName = UCase(NTService.ServiceName)
If ServiceName = UCase(TargetName) And NTService.ProcessID <> 0 Then
DumpProcessID RuleFolder, NTService.ProcessID
Exit For
End If
Next
End Sub
Sub Controller_OnHTTPPingError(ByVal FailedURL)
WriteToLog FormatString("HTTP Ping Error:",25) & " Ping URL - " & _
FailedURL.URL & " Status Code - " & FailedURL.LastStatusCode & _
" Status Text - " & FailedURL.LastStatusText
End Sub
Sub Controller_OnHTTPPingTimeout(ByVal TimedOutURL)
WriteToLog FormatString("HTTP Ping Timeout:",25) & " Ping URL - " & _
TimedOutURL.URL & " Timeout(secs) - " & TimedOutURL.TimeoutInterval
HandleIISHangRule TimedOutURL
End Sub
Function GetControlScriptForService(ByVal Service)
GetControlScriptForService = ""
ServiceName = UCase(Service.ServiceName)
End Function
Function GetControlScriptForProcess(ByVal Process)
GetControlScriptForProcess = ""
End Function
Sub CreatePingURLs()
End Sub
Sub HandleIISHangRule(ByVal TimedOutURL)
End Sub
'----------------------------------------------------------------------------
'Modified Code - Start
Class TriggerItem
Private m_processName
Public CounterPath
Public CounterLimits
Public ProcessID
Public ProcessIndex
Public TriggerID
Private Sub Class_Initialize
m_processName = ""
CounterPath = ""
CounterLimits = Array()
ProcessID = 0
ProcessIndex = 0
TriggerID = 0
End Sub
Public Sub AddLimit(ByVal limit)
ReDim Preserve CounterLimits(UBound(CounterLimits) + 1)
CounterLimits(UBound(CounterLimits)) = limit
End Sub
Public Sub RemoveFirstLimit()
If UBound(CounterLimits) = 0 Then
CounterLimits = Array()
Else
newLimits = Array(UBound(CounterLimits) - 1)
For i = 0 To UBound(newLimits)
newLimits(i) = CounterLimits(i + 1)
Next
CounterLimits = newLimits
End If
End Sub
Public Property Get LimitCount
LimitCount = UBound(CounterLimits) + 1
End Property
Public Property Get ProcessName
ProcessName = m_processName
End Property
Public Property Let ProcessName(ByVal value)
m_processName = LCase(value)
End Property
End Class
Class TriggerItems
Private m_processes
Private Sub Class_Initialize
Set m_processes = CreateObject("Scripting.Dictionary")
'Create a fictitious trigger to avoid hanging DbgSvc.exe when triggers are empty.
Controller.PerfWatcher.CreatePerfTrigger "\Process(foo)\Working Set", False, 1024*1024*1024*5, 1
End Sub
Private Function GetDictionary(ByVal processName)
Set GetDictionary = Nothing
processName = LCase(processName)
If m_processes.Exists(processName) Then
Set GetDictionary = m_processes.Item(processName)
End If
End Function
Private Sub LogTriggerInfo(ByVal message, ByRef trigger)
WriteToLog message & vbCRLF & _
" PerfTriggerID = " & trigger.PerfTriggerID & vbCrLf & _
" CounterPath = " & trigger.CounterPath & vbCrLf & _
" TriggerIfAbove = " & trigger.TriggerIfAbove & vbCrLf & _
" Limit = " & trigger.Limit & vbCrLf & _
" LastValue = " & trigger.LastValue & vbCrLf & _
" SecondsOutsideLimit = " & trigger.SecondsOutsideLimit
End Sub
Public Sub Add(ByRef process, ByVal injectLeakTrack, ByVal counterPath, ByVal limit)
Set items = GetDictionary(process.ProcessName)
If items Is Nothing Then
Set items = CreateObject("Scripting.Dictionary")
m_processes.Add LCase(process.ProcessName), items
End If
If Not items.Exists(process.ProcessID) Then
If injectLeakTrack Then
process.InjectLeakTrack
WriteToLog "Injected LeakTrack.dll into PID:" & process.ProcessID
End If
perfmonName = LCase(Left(process.ProcessName, Len(process.ProcessName) - 4))
If InStr(counterPath, "{0}") > 0 Then
If items.Count > 0 Then
perfmonName = perfmonName & "#" & CStr(items.Count)
End If
counterPath = Replace(counterPath, "{0}", perfmonName)
End If
Set trigger = Controller.PerfWatcher.CreatePerfTrigger(counterPath, True, limit, 1)
LogTriggerInfo "New trigger has been created:", trigger
Set itm = New TriggerItem
itm.CounterPath = trigger.CounterPath
itm.TriggerID = trigger.PerfTriggerID
itm.ProcessName = process.ProcessName
itm.ProcessID = process.ProcessID
itm.ProcessIndex = items.Count
itm.AddLimit(limit)
items.Add process.ProcessID, itm
Else
Set itm = items.Item(process.ProcessID)
itm.AddLimit(limit)
End If
End Sub
Public Sub Remove(ByRef process)
'When a process exits, the perf triggers don't change at all.
' ... so we need to do a shift, delete or re-add of various
' triggers to keep the PID's and triggers matched up.
Set items = GetDictionary(process.ProcessName)
If Not items Is Nothing Then
If items.Exists (process.ProcessID) Then
Set removing = items.Item(process.ProcessID)
items.Remove process.ProcessID
lastCounterPath = removing.CounterPath
lastTriggerID = removing.TriggerID
savedCounterPath = lastCounterPath
savedTriggerID = lastTriggerID
keys = items.Keys
For i = removing.ProcessIndex To UBound(keys)
Set itm = items.Item(keys(i))
savedCounterPath = itm.CounterPath
savedTriggerID = itm.TriggerID
If (itm.TriggerID <> -1) Then
If (lastTriggerID <> -1) Then
'Shift path
itm.CounterPath = lastCounterPath
'Shift Trigger
itm.TriggerID = lastTriggerID
Else'(lastTriggerID = -1)
'Shift path
itm.CounterPath = lastCounterPath
'Create a new trigger
WriteToLog "Re-adding """ & itm.CounterPath & """ because it matches PID:" & itm.ProcessID & " which has not hit its trigger limit"
Set trigger = Controller.PerfWatcher.CreatePerfTrigger(itm.CounterPath, True, itm.CounterLimits(0), 1)
itm.TriggerID = trigger.PerfTriggerID
End If
End If
If (itm.TriggerID = -1) Then
If (lastTriggerID <> -1) Then
'Shift path
itm.CounterPath = lastCounterPath
'Delete trigger
WriteToLog "Removing """ & itm.CounterPath & """ because it matches PID:" & itm.ProcessID & " which already hit its trigger limit"
Controller.PerfWatcher.RemovePerfTrigger lastTriggerID
Else'(lastTrigger = -1)
'Shift path
itm.CounterPath = lastCounterPath
'Don't do anything with triggers
End If
End If
itm.ProcessIndex = i
lastCounterPath = savedCounterPath
lastTriggerID = savedTriggerID
Next
'Okay... we've gone through the whole list for this particular processName
'The last one in the list will always have the highest CounterPath
'Remove it otherwise the shifting we just did will leave this without a matching PID.
If lastTriggerID = -1 Then
WriteToLog "Cannot remove trigger for """ & lastCounterPath & """ because it was previously removed."
Else
WriteToLog "Removing highest trigger """ & lastCounterPath & """ to account for exiting process"
Controller.PerfWatcher.RemovePerfTrigger lastTriggerID
End If
End If
End If
End Sub
Public Sub Triggered(ByRef trigger)
'There is no information in the DebugDiag trigger that tells us what PID just exceeded the trigger.
'Iterate through all the TriggerItems to find the matching TriggerID so we can create a DMP based on the right PID.
For Each process in m_processes.Items
For Each itm in process.Items
If CInt(itm.TriggerID) = CInt(trigger.PerfTriggerID) Then
LogTriggerInfo "OnPerfTriggerHit fired for PID:" & itm.ProcessID, trigger
Controller.PerfWatcher.RemovePerfTrigger itm.TriggerID
itm.RemoveFirstLimit()
If itm.LimitCount = 0 Then
WriteToLog "No additional limits for PID:" & itm.ProcessID & ". Removing its trigger(s)."
itm.TriggerID = -1
End If
Set ActiveProcess = Controller.Processes.GetProcessByProcessID(itm.ProcessID)
DumpName = ActiveProcess.CreateDump("PerfTrigger_Fired")
WriteToLog "Created dump file " & DumpName
If itm.LimitCount > 0 Then
Set trigger = Controller.PerfWatcher.CreatePerfTrigger(itm.CounterPath, True, itm.CounterLimits(0), 1)
itm.TriggerID = trigger.PerfTriggerID
LogTriggerInfo "PID:" & itm.ProcessID & " has additional limits configured. Creating trigger for next limit:", trigger
End If
Exit Sub
End If
Next
Next
End Sub
End Class
'Modified Code - End
'----------------------------------------------------------------------------
DbgSVC.vbs code for Sample 2: PerfmonTriggerSample
' Note make modifications to processes/counters/thresholds at line 61.
' Note make modifications to the actions taken beginning at line 83.
Const SymbolPath = "SRV*C:\symbols*https://msdl.microsoft.com/download/symbols"
Set ServiceState = Controller.ServiceState
Set HTTPPinger = Controller.HTTPPinger
Sub WriteToLog(ByVal Output)
Controller.Write "[" & Now() & "] "
Controller.Write Output & vbCRLF
End Sub
Function FormatString(ByVal InputString, ByVal FieldLength)
FormatString = InputString
If Len(InputString) < FieldLength Then
FormatString = FormatString & Space(FieldLength - Len(InputString))
End If
End Function
Sub Controller_OnStart()
Dim NewTrigger
WriteToLog "DbgSvc started"
CreatePingURLs
If ServiceState("PERFLOG_INTERVAL") = 0 Then
ServiceState("PERFLOG_INTERVAL") = 60 * 5 ' Default hardcoded sampling interval = 5 minutes
End If
Set PerfLog = Controller.PerfLog
PerfLog.Interval = ServiceState("PERFLOG_INTERVAL")
If ServiceState("DISABLE_PERFLOG") <> 1 Then
On Error Resume Next
' These counters could be missing from the system if IIS and/or ASP.Net is not installed
' In Win2K3 there is no TCP object! Instead there are TCPv4 and TCPv6.
PerfLog.AddCounter "\ASP.NET\*"
PerfLog.AddCounter "\Active Server Pages\*"
PerfLog.AddCounter "\Web Service(*)\*"
PerfLog.AddCounter "\TCP\*"
If Err.Number <> 0 Then
' Only add these counters if TCP failed (Win2K3)
PerfLog.AddCounter "\TCPv4\*"
PerfLog.AddCounter "\TCPv6\*"
End If
PerfLog.AddCounter "\\Internet Information Services Global\\*"
On Error Goto 0
PerfLog.AddCounter "\Memory\*"
PerfLog.AddCounter "\Process(*)\*"
PerfLog.AddCounter "\Processor(*)\*"
PerfLog.AddCounter "\System\*"
PerfLog.Start
End If
' We want notification when our counter exeeds 10,000 miliseconds for any longer than 1 second
Set NewTrigger = Controller.PerfWatcher.CreatePerfTrigger("\ASP.NET\Request Execution Time", True, 80000, 1)
' Store the PerfTrigger ID
ServiceState("PERFTRIGGER_ASPNETEXECUTIONTIME_ID") = NewTrigger.PerfTriggerID
' How many times do we want to act on the perf trigger?
ServiceState("PERFTRIGGER_ACTIONLIMIT_" & NewTrigger.PerfTriggerID) = 1
' Reset the action counter
ServiceState("PERFTRIGGER_ACTIONCOUNT_" & NewTrigger.PerfTriggerID) = 0
' Write out new PerfTrigger info
WriteToLog "NewTrigger Has Been Created:" & vbCRLF & _
"--------------------------" & vbCRLF & _
"PerfTriggerID = " & NewTrigger.PerfTriggerID & vbCRLF & _
"CounterPath = " & NewTrigger.CounterPath & vbCRLF & _
"TriggerIfAbove = " & NewTrigger.TriggerIfAbove & vbCRLF & _
"Limit = " & NewTrigger.Limit & vbCRLF & _
"LastValue = " & NewTrigger.LastValue & vbCRLF & _
"SecondsOutsideLimit = " & NewTrigger.SecondsOutsideLimit
End Sub
Sub Controller_OnPerfTriggerHit(ActiveTrigger)
Dim nActionLimit, nActionCount
Dim DumpName, ActiveProcess
WriteToLog "OnPerfTriggerHit fired for counter: " & ActiveTrigger.CounterPath
Select Case ActiveTrigger.PerfTriggerID
Case ServiceState("PERFTRIGGER_ASPNETEXECUTIONTIME_ID")
' Do whatever you want here, i.e. create a dump file
WriteToLog "Taking action on the following PerfTrigger:" & vbCRLF & _
"--------------------------" & vbCRLF & _
"PerfTriggerID = " & ActiveTrigger.PerfTriggerID & vbCRLF & _
"CounterPath = " & ActiveTrigger.CounterPath & vbCRLF & _
"TriggerIfAbove = " & ActiveTrigger.TriggerIfAbove & vbCRLF & _
"Limit = " & ActiveTrigger.Limit & vbCRLF & _
"LastValue = " & ActiveTrigger.LastValue & vbCRLF & _
"SecondsOutsideLimit = " & ActiveTrigger.SecondsOutsideLimit
For Each ActiveProcess In Controller.Processes
If UCase(ActiveProcess.ProcessName) = "W3WP.EXE" Then
DumpName = ActiveProcess.CreateDump("PerfTrigger Fired")
WriteToLog "Created dump file " & DumpName
Exit For
End If
Next
End Select
' Keep track of the action count
nActionCount = ServiceState("PERFTRIGGER_ACTIONCOUNT_" & ActiveTrigger.PerfTriggerID)
nActionCount = nActionCount + 1
ServiceState("PERFTRIGGER_ACTIONCOUNT_" & ActiveTrigger.PerfTriggerID) = nActionCount
' Remove this trigger if we've exceeded our action limit
nActionLimit = ServiceState("PERFTRIGGER_ACTIONLIMIT_" & ActiveTrigger.PerfTriggerID)
If nActionCount >= nActionLimit Then
WriteToLog "Action limit of " & nActionLimit & " was reached. (nActionCount = " & nActionCount & ") Removing PerfTrigger."
Controller.PerfWatcher.RemovePerfTrigger ActiveTrigger.PerfTriggerID
End If
End Sub
Sub Controller_OnShutdown()
WriteToLog "DbgSVC stopped"
End Sub
Sub Controller_OnProcessExited(ByVal ExitingProcess)
Dim Message
Message = FormatString("Process Exited:",25) & " Process Name - " & FormatString(ExitingProcess.ProcessName,20) & _
" Process ID - " & FormatString(ExitingProcess.ProcessID, 6)
If ExitingProcess.COMPlusPackageName <> "" Then
Message = Message & " MTS/COM+ package name - " & ExitingProcess.COMPlusPackageName
ElseIf ExitingProcess.WebAppPoolName <> "" Then
Message = Message & " Web application pool name - " & ExitingProcess.WebAppPoolName
End If
WriteToLog Message
End Sub
Sub HandleProcess(ByVal Process, ByVal ControlScript)
If Process.IsDebuggerAttached Then
WriteToLog FormatString("Reload Control Script:",25) & " Process Name - " & FormatString(Process.ProcessName,20) & _
" Process ID - " & FormatString(Process.ProcessID, 6) & " Control Script - " & ControlScript
Process.ReloadControlScript ControlScript
ElseIf Not Process.IsBeingDebugged Then
WriteToLog FormatString("Attach Debugger:",25) & " Process Name - " & FormatString(Process.ProcessName,20) & _
" Process ID - " & FormatString(Process.ProcessID, 6) & " Control Script - " & ControlScript
Process.AttachToProcess ControlScript, SymbolPath, ""
Else
WriteToLog FormatString("Unknown Debugger:",25) & " Process Name - " & FormatString(Process.ProcessName,20) & _
" Process ID - " & FormatString(Process.ProcessID, 6)
End If
End Sub
Sub HandleService(ByVal Service)
If Service.ProcessID <> 0 and Service.CurrentState = "SERVICE_RUNNING" Then
ControlScript = GetControlScriptForService(Service)
If ControlScript <> "" Then
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(Service.ProcessID)
If Not Process Is Nothing Then
HandleProcess Process, ControlScript
End If
End If
End If
End Sub
Sub Controller_OnNewServiceFound(ByVal NewService)
WriteToLog FormatString("New service found:",25) & " Service Name - " & FormatString(NewService.ServiceName, 20) & _
" Process ID - " & FormatString(NewService.ProcessID, 6) & " Current State - " & NewService.CurrentState
HandleService NewService
End Sub
Sub Controller_OnServiceStateChanged(ByVal AffectedService)
WriteToLog FormatString("Service state changed:",25) & " Service Name - " & FormatString(AffectedService.ServiceName,20) & _
" Process ID - " & FormatString(AffectedService.ProcessID, 6) & " Current State - " & AffectedService.CurrentState
HandleService AffectedService
End Sub
Sub Controller_OnNewProcessFound(ByVal NewProcess)
Dim Message
Dim GFlags
Message = FormatString("New process found:",25) & " Process Name - " & FormatString(NewProcess.ProcessName,20) & _
" Process ID - " & FormatString(NewProcess.ProcessID, 6) & " Process Identity - " & FormatString(NewProcess.ProcessIdentity, 40)
GFlags = Controller.GetGlobalFlagForProcess(NewProcess.ProcessName)
If GFlags <> "" Then
Message = Message & " Global Flags - " & FormatString(GFlags, 12)
End If
If NewProcess.COMPlusPackageName <> "" Then
Message = Message & " MTS/COM+ package name - " & NewProcess.COMPlusPackageName
ElseIf NewProcess.WebAppPoolName <> "" Then
Message = Message & " Web application pool name - " & NewProcess.WebAppPoolName
End If
WriteToLog Message
ControlScript = GetControlScriptForProcess(NewProcess)
If ControlScript <> "" Then HandleProcess NewProcess, ControlScript
End Sub
Sub StartLeakRule(ByVal ProcessID)
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(ProcessID)
If Process Is Nothing Then
WriteToLog FormatString("Start Leak Rule Failed:",25) & " Process ID - " & _
FormatString(ProcessID, 6) & " Process Not Found"
Else
Process.InjectLeakTrack
WriteToLog FormatString("Leak Rule Started:",25) & " Process ID - " & _
FormatString(ProcessID, 6)
End If
End Sub
Sub StopLeakRule(ByVal ProcessID, ByVal RuleFolder, ByVal bUnloadLeakTrack)
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(ProcessID)
If Process Is Nothing Then
WriteToLog FormatString("Stop Leak Rule Failed:",25) & " Process ID - " & _
FormatString(ProcessID, 6) & " Process Not Found"
Else
DumpPath = Process.CreateDump("Leak Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(ProcessID, 6) & " Dump Path - " & DumpPath
If bUnloadLeakTrack Then
Process.UnloadLeakTrack
WriteToLog FormatString("Leak Rule Stopped:",25) & " Process ID - " & _
FormatString(ProcessID, 6)
End If
End If
End Sub
Sub DumpAllIISProcesses(ByVal RuleFolder)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
ProcessName = UCase(Process.ProcessName)
Select Case ProcessName
Case "INETINFO.EXE", "MTX.EXE", "DLLHOST.EXE", "DLLHST3G.EXE", "W3WP.EXE", "ASPNET_WP.EXE"
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End Select
Next
End Sub
Sub DumpProcess(ByVal RuleFolder, ByVal TargetName)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
ProcessName = UCase(Process.ProcessName)
If ProcessName = UCase(TargetName) Then
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End If
Next
End Sub
Sub DumpCOMPlusApp(ByVal RuleFolder, ByVal TargetName)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
PackageName = UCase(Process.COMPlusPackageName)
If PackageName = UCase(TargetName) Then
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End If
Next
End Sub
Sub DumpWebAppPool(ByVal RuleFolder, ByVal TargetName)
Set ProcessManager = Controller.Processes
For each Process in ProcessManager
AppPoolName = UCase(Process.WebAppPoolName)
If AppPoolName = UCase(TargetName) Then
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End If
Next
End Sub
Sub DumpProcessID(ByVal RuleFolder, ByVal TargetPID)
Set ProcessManager = Controller.Processes
Set Process = ProcessManager.GetProcessByProcessID(TargetID)
DumpPath = Process.CreateDump("IIS Hang Dump", RuleFolder)
WriteToLog FormatString("Process Dump Created:",25) & " Process ID - " & _
FormatString(Process.ProcessID, 6) & " Dump Path - " & DumpPath
End Sub
Sub DumpNTService(ByVal RuleFolder, ByVal TargetName)
Set ServiceManager = Controller.Processes
For each NTService in ServiceManager
ServiceName = UCase(NTService.ServiceName)
If ServiceName = UCase(TargetName) And NTService.ProcessID <> 0 Then
DumpProcessID RuleFolder, NTService.ProcessID
Exit For
End If
Next
End Sub
Sub Controller_OnHTTPPingError(ByVal FailedURL)
WriteToLog FormatString("HTTP Ping Error:",25) & " Ping URL - " & _
FailedURL.URL & " Status Code - " & FailedURL.LastStatusCode & _
" Status Text - " & FailedURL.LastStatusText
End Sub
Sub Controller_OnHTTPPingTimeout(ByVal TimedOutURL)
WriteToLog FormatString("HTTP Ping Timeout:",25) & " Ping URL - " & _
TimedOutURL.URL & " Timeout(secs) - " & TimedOutURL.TimeoutInterval
HandleIISHangRule TimedOutURL
End Sub
Function GetControlScriptForService(ByVal Service)
GetControlScriptForService = ""
ServiceName = UCase(Service.ServiceName)
End Function
Function GetControlScriptForProcess(ByVal Process)
GetControlScriptForProcess = ""
End Function
Sub CreatePingURLs()
End Sub
Sub HandleIISHangRule(ByVal TimedOutURL)
End Sub