Automating dump file analysis via powershell for Citrix XenApp
Here is an automated task to analyze Windows Server dump files and e-mail a distribution list with the explanation of the OS failure. The script provides System Administrators with a quick window of what may be the root causes of BSODs, denial of service, etc.
The dump file analysis script is broken down into two scripts, a launch script, and a script housed on a file server that performs all of the analysis. The script below will gather all server names in a specific OU(s), appends the names to a text file located on C:\Servers.txt, and runs the crashreport.ps1 script.
# Launch_crashreport.ps1
# Launch debug analysis logs using KD
# Kevin Patrick 1/26/2011
#
# Usage: ./launch_crashreport.ps1
#
# Output: Log file to standard output to C:\Windows\dumpsprocessed
#
# Note: Powershell and Debugging Tools for Windows must be installed
#
#################################################################################################################
#OU dump
$strCategory = “computer”
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objOU = New-Object System.DirectoryServices.DirectoryEntry(“LDAP://OU=OU,OU=OU,OU=OU,DC=DC,DC=XX.com”)
#$objOU = New-Object System.DirectoryServices.DirectoryEntry(“LDAP://OU=OU,OU=OU,OU=OU,DC=DC,DC=XX.com”)
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objOU
$objSearcher.Filter = (“(objectCategory=$strCategory)”)
$colResults = $objSearcher.FindAll()
#Output server names in OU to C:\servers.txt on launch server
foreach ($objResult in $colResults)
{$objComputer = $objResult.Properties; $objComputer.name | Out-File “c:\servers.txt” -append}
#Invoke-Command -filePath example in PowerShell 2.0
invoke-Command -computerName (Get-Content “C:\Servers.txt”) -filePath “\\FileServer\FileShare\Crashreport.ps1”
#Delete C:\servers.txt from launch server. -append above will continually add server names to .txt file without logic.
del “c:\servers.txt”
Add the script above to a scheduled task that runs once a day, or whatever intervals you desire.
Also, run the following commands on each server to allow PSRemoting and to open the execution policy.
Powershell.exe set-executionpolicy unrestricted
powershell.exe enable-psremoting -force
# crashreport.ps1
# Create debug analysis logs using KD
# Kevin Patrick 1/21/2011
#
# Usage: ./crashreport.ps1
#
#
# Output: Log file to standard output to C:\Windows\dumpsprocessed
#
# Note: Debugging Tools for Windows must be installed
# in its default directory (Program Files (X86)\Debugging Tools For Windows)
#
$Notify = “someone@somewhere.com”
$timestamp = $(Get-Date -f hh.mm.ss_dd.MM.yy)
$dumpmove = $ENV:WinDIR + “\dumpsprocessed\” + $timestamp
$crashdumpfile = $ENV:WinDIR + “\minidump*.dmp”
$crashdumpfile2 = $ENV:WinDIR + “*.dmp”
#If C:\Windows\dumprocessed dir does not exist, create dir
if (!(Test-Path -path $dumpmove))
{
New-Item $dumpmove -type directory
}
Set-Alias kd “C:\Program Files (x86)\Debugging Tools for Windows (x86)\kd.exe”
# Debug commands are specified here. See the Debugging Tools For
# Windows for more details
#
# Commands are: !analyze -v Verbose analysis of the crash
# kv Stacktrace
# !process Current process and thread at crash
# lmf List loaded modules and file paths
# q quit KD (or else KD will keep running)
#
$debugcommands = “`”!analyze -v; kv; !process; lmf; q`””
# PowerShell Foreach to generate crashdump file
clear host
Get-ChildItem $crashdumpfile | foreach{
$logfile = $dumpmove + “\” + $_.name + “.log”
# Execute kd with commands
kd -c $debugcommands -noshell -logo $logfile -z $_.fullname
#Screen output
Add-Content $logfile (“`n Finished debugging: ” + $_.fullname )
Add-Content $logfile (“`n Debug Output to log file: ” + $logfile)
Add-Content $logfile (“`n Processed dump files and log files can be found: ” + $dumpmove)
#Email
$Message = (Get-Content $logfile)
$Message = [string]::join([environment]::NewLine,$Message)
$mail = New-Object System.Net.Mail.MailMessage
#set the addresses
$mail.From = New-Object System.Net.Mail.MailAddress(“dump_analyses” + “@” + $Env:COMPUTERNAME + “.domain.com”);
$mail.To.Add($Notify);
#set the content
$mail.Subject = “$Env:COMPUTERNAME – $_ was analyzed”
$mail.Body = $Message;
#send the message
$smtp = new-object System.Net.Mail.SmtpClient(“smtpserver.somewhere.com”);
#to authenticate we set the username and password properites on the SmtpClient
#$smtp.Credentials = new-object System.Net.NetworkCredential(“username”, “password”);
$smtp.Send($mail);
#Move proccessed .dmp file to C:\Winodws\dumpsprocessed
move $_.fullname $dumpmove }
# PowerShell Foreach to generate crashdump file
clear host
Get-ChildItem $crashdumpfile2 | foreach{
$logfile = $dumpmove + “\” + $_.name + “.log”
# Execute kd with commands
kd -c $debugcommands -noshell -logo $logfile -z $_.fullname
#Screen output
Add-Content $logfile (“`n Finished debugging: ” + $_.fullname )
Add-Content $logfile (“`n Debug Output to log file: ” + $logfile)
Add-Content $logfile (“`n Processed dump files and log files can be found: ” + $dumpmove)
#Email
$Message = (Get-Content $logfile)
$Message = [string]::join([environment]::NewLine,$Message)
$mail = New-Object System.Net.Mail.MailMessage
#set the addresses
$mail.From = New-Object System.Net.Mail.MailAddress(“dump_analyses” + “@” + $Env:COMPUTERNAME + “.domain.com”);
$mail.To.Add($Notify);
#set the content
$mail.Subject = “$Env:COMPUTERNAME – $_ was analyzed”
$mail.Body = $Message;
#send the message
$smtp = new-object System.Net.Mail.SmtpClient(“smtpserver.domain.com”);
#to authenticate we set the username and password properites on the SmtpClient
#$smtp.Credentials = new-object System.Net.NetworkCredential(“username”, “password”);
$smtp.Send($mail);
#Move proccessed .dmp file to C:\Winodws\dumpsprocessed
move $_.fullname $dumpmove
#Cleanup empty folder in C:\Windows\dumpsprocessed
$cleanup = Get-ChildItem “C:\Windows\dumpsprocessed” -Recurse
foreach($item in $cleanup)
{
if( $item.PSIsContainer )
{
$subitems = Get-ChildItem -Recurse -Path $item.FullName
if($subitems -eq $null)
{
“Remove item: ” + $item.FullName
Remove-Item $item.FullName
}
$subitems = $null
}