Searching ULS Logs in Multi-Server Farms

If you have from 5 to a lot more SharePoint servers in your farm, and you need to locate a specific error in the ULS logs, well, it can be a pain. I’ve written a PowerShell script that will allow you to specify what column the error is in, when the error happened, and the general text of the error. The script will take your input and search the ULS logs on each server in the farm. There are the normal cautions about long searches, etc, but you should already know that.

The output is 2 files, one is a standard ULS log file that ULSViewer can open, the other is a short file, which contains the errors from the ULS with just a few fields.

Last thing, please feel free to make fun of my PowerShell scripting abilities. Everyone else I know does…

#Load up the SharePoint cmdlets if they are missing
if (!(Get-PsSnapin | Where-Object {$_.Name -match "Microsoft.SharePoint.PowerShell"}))
{Add-PsSnapin Microsoft.SharePoint.PowerShell}

$FarmInfo = Get-SPFarm
$spLogLocation = (Get-SPDiagnosticConfig | select -expand LogLocation)
$spLogLocation = "\" + ($spLogLocation -replace (":","$"))

$outputFile = "ULSSearchResults.log"
$fulloutputFile = "ULSViewerVersion.log"


if ((test-path $outputFile) -eq "True") {Remove-Item $outputFile -force}
if ((test-path $fulloutputFile) -eq "True") {Remove-Item $fulloutputFile -force}

$DateCheck = date
Add-Content $outputFile "ULS Error Search - Started $DateCheck"
Add-Content $outputFile "`r"

Clear-Host
Write-Host @"
Choose which ULS Column To Search In
------------------------------------
A:  Correlation ID
B:  Message
C:  Category
D:  EventID
E:  Level
F:  All Areas (Caution, this will take a long time to complete)
`r
"@

$q1 = Read-Host "Column"
$q1 = $q1.ToUpper()

If($q1 -eq "A"){$logcat = "Correlation"}
 elseif($q1 -eq "B"){$logcat = "Message"}
 elseif($q1 -eq "C"){$logcat = "Category"}
 elseif($q1 -eq "D"){$logcat = "EventID"}
 elseif($q1 -eq "E"){$logcat = "Level"}
 elseif($q1 -eq "F"){$logcat = "ALL"}
Else{
	Write-Host "`r"
	Write-Host "Selection Is Outside Of Accepted Values.  Rerun Script And Make A Valid Selection." -foregroundcolor "Yellow"
	Break}
 
Write-Host @"
`r
`r
Choose A TimeFrame To Search In
-------------------------------
A:  Last 10 minutes
B:  Last 30 Minutes
C:  Last 60 Minutes
D:  Last 12 Hours
E:  All Log Files
`r
"@

$q2 = Read-Host "TimeFrame"
$q2 = $q2.ToUpper()

If($q2 -eq "A"){$timcat = "10"}
 elseif($q2 -eq "B"){$timcat = "30"}
 elseif($q2 -eq "C"){$timcat = "60"}
 elseif($q2 -eq "D"){$timcat = "720"}
 elseif($q2 -eq "E"){$timcat = "ALL"}
Else{
	Write-Host "`r"
	Write-Host "Selection Is Outside Of Accepted Values.  Rerun Script And Make A Valid Selection." -foregroundcolor "Yellow"
	Break}

If($timcat -eq "ALL"){$tframe = "All Log Files"}
 Else
 {$tframe = $timcat + " Minutes Ago"}

Write-Host @"
`r
`r
Enter or Paste In The Text To Search For
----------------------------------------
`r
"@

$errMsg = Read-Host "Error"

Add-Content $outputFile @"
*****  Begin ULS Log Search For Error:  $errMSG
Checking In Column: $logcat.  Within The Timeframe Of: $tframe
`r
--------------------------------------------------------------------------------
`r
ServerName`tTimeStamp`tEventID`tCategory`tLevel`tCorrelationID`tMessage
"@


$timeframe = $null
$FarmServers = $FarmInfo.Servers | Where-Object {$_.Role -ne "Invalid"}
If($timcat -ne "ALL"){$timeframe = (Get-Date).AddMinutes(-$timcat)}
Write-Host "`r"

ForEach($spServer in $FarmServers){
	$logPath = "\\$($spServer.Address)" + $spLogLocation
	Write-Host "Processing Logs File At:  $logPath"
	
	If($timcat -ne "ALL"){
		If($logcat -ne "ALL"){$logResults = Get-SPLogEvent -Starttime $timeframe -Directory $logPath | Where-Object{$_.$logcat -like "*$errMsg*"}}
		Else
		{$logResults = Get-SPLogEvent -Starttime $timeframe -Directory $logPath | Where-Object{$_ -like "*$errMsg*"}}
	}
	Else
		 {If($logcat -ne "ALL"){$logResults = Get-SPLogEvent -Directory $logPath | Where-Object{$_.$logcat -like "*$errMsg*"}}
		 Else
		 {$logResults = Get-SPLogEvent -Directory $logPath | Where-Object{$_ -like "*$errMsg*"}}
	}
	
	Add-Content $fulloutputFile $logResults
	
	ForEach($loggedItem in $logResults){
		$shortMessage = ($loggedItem.Message)
		If(($shortMessage.Length) -gt 125){$shortMessage = $shortMessage.SubString(0,125)}
		If($shortMessage -ne $Null){
		Add-Content $outputFile "$($spServer.Address)`t$($loggedItem.Timestamp)`t$($loggedItem.EventID)`t$($loggedItem.Category)`t$($loggedItem.Level)`t$($loggedItem.Correlation)`t$shortMessage"}}
	}
Write-Host @"
`r
ULS Log Search Complete
Simple output file:  $outputFile
ULSViewer compatible file:  $fulloutputFile
`r
"@

Finding WebSite Admins and Total List Items

This single line command will export Site Admins and List Item Count for every website in a given WebApplication. Very useful if the boss wants to shell out zero dollars for an auditing system.

 Get-SPWebApplication "<webappURL>" | select -expandproperty Sites |%{Get-SPWeb $_.URL} |%{$g1=($_.Lists | ?{$_.hidden -eq $false} |select ParentWebURL,Title,ItemCount,BaseType) ; $g2=($_.SiteAdministrators |Select -expand "DisplayName"); Add-Content "ReportFile.csv" "$g2,$g1"}