-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathExchSetupLog-Assistant.ps1
More file actions
187 lines (186 loc) · 10.8 KB
/
ExchSetupLog-Assistant.ps1
File metadata and controls
187 lines (186 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
Function ExchSetupLog-Assistant {
Param (
#Stage Variable for Exchange setup log path:
$Log = ".\ExchangeSetup.log",
#Stage Variable for base string that we expect in every line of the log:
$BaseString = "]",
#Target Error count per install:
[int]$ErrorCount = "12",
#How many of the last attempts do you want to review?
[int]$Lastattempts = "3",
#Do we want to review the entire log?## At this time, we will still index the entire log
[boolean]$EntireLog = $false,
#Do we want to place focused log into variable?
[boolean]$ExportLogToShell = $true,
#Do we want to export the log highlight to a local directory?
[boolean]$ExportLogToLog = $false,
#Log directory export path:
[string]$ExportPath = (Get-Location).Path,
#Do we want live review?
[boolean]$LiveReview = $false,
#What is the custom formatting we want between Attempt number and whether entry is Status,Timeline, or error
[string]$Character = "__",
#Include Raw strings on exception:
[boolean]$RawStringonTermination = $true,
#Number of strings to include:
[int]$RawStringscount = "30"
)
#Stage variable for the key point in log:
[string]$Key = "Starting Microsoft Exchange Server"+"*"+"Setup"
#Stage an array of base strings that help with timeline:
[String[]]$TimelineStrings = "Server Name=","Logged on User:","Command Line Parameter Name=","OrganizationName","MSExchangeADTopology has a persisted domain controller:","Setup Version:", "Operating System Version:", "PrepareAD has", "The Schema "," End of Setup","Starting copy from","Finished Copy from","Setup will use"
#Stage an array for status strings:
[String[]]$StatusStrings = "Organization Configuration Update Required Status :","Schema Update Required Status :", "Setup encountered a problem while validating the state of Active Directory", "Domain Configuration Update Required Status :", "Setup has detected","The Exchange Server setup operation didn't complete.","tasks were found to run.","A reboot from a previous installation is pending","The local domain needs to be updated.", "RestoreServerOnPrereqFailure.ps1"
#Variable containing hard stop message:
[String[]]$KeyFail = "Setup is stopping now because of one or more critical errors", "The Exchange Server setup operation didn't complete."
#Variable containing desired error strings:
[String[]]$Failstrings = "Error","Critical","Terminate","Fail","errors","failure","warining"
#Variable containing success strings:
[string[]]$SuccessStrings = "The Exchange Server setup operation completed successfully.","Install is complete. "
#Variable containing ignore strings: #### For now, this only applies to Errors!####
[string[]]$IgnoreStrings = "RuleType:Error","ErrorAction:","RuleType:Warning","Setting:ADinitError","HasException:False","RestoreServerOnPrereqFailure.ps1"," finished "
#Get the entire log into string array varible:
$TotalLog = GCI $Log |Sls $BaseString
#stage an integer containing the total count of entries in the log
[int]$TotalLogCount = $totallog.count
Write-Host "There are " $totallogcount " entries in this log"
#Ensure our counts are at 0:
[int]$TerminalLoop = "0"
[int]$I = "0"
[int]$e = "0"
#Create index:
$Global:ExchSetupIndex = New-Object PsCustomObject
#Enter Foreach Loop for Index build & Key:
Foreach ($entry in $totalLog) {
#Increment number by 1 to know which string this is in the sequence of strings
$I ++
#If Entry is like our key:
If ($entry -like "*"+$key+"*") {
#Increment number by 1 for the number of key hits we have:
$IndexHits ++
#Then add the number in sequence of strings to our index of instance of hits
$ExchSetupIndex | Add-Member -MemberType NoteProperty -Name ("Key" + $indexHits) -Value $I
#Add what the entry is to the index so we can include time stamp of setup
$ExchSetupIndex | Add-Member -MemberType NoteProperty -Name ("Key" + $indexHits+ "Entry") -Value $Entry
Write-Host "Found Index hit at entry number" $I}
}
##Now that we are indexed, what kind of strings do we find in the desired index?##
#Catch if there are less entries than the specified number of attempts:
If ($LastAttempts -ge $IndexHits) {$entirelog = $true}
#If we want to reference the index:
If ($entirelog -eq $false) {
#Which of the keys do we care about? (Number of key hits versus the user specified number)
[string]$KeyIndexes = $IndexHits-$LastAttempts+1
#Stage string of what we expect the property to be called:
[string]$KeyReference = "Key"+$KeyIndexes
#Stage an integer containing the number of key indexes:
[int]$StartingPoint = ($ExchSetupIndex).$KeyReference - 1
#Reference the property specified on the index, then get it's definition, then use that number found to reference that point in the index to the end of the log:
$Global:FocusedExchLog =$totallog[$StartingPoint..$TotalLogCount]}
#If we want the entire log, set focused log to total log
If ($entirelog -eq $true) {$Global:FocusedExchLog = $TotalLog}
##Now let's search the specified range:
Foreach ($entry in $FocusedExchLog) {
#Increment variable so we know where we are in the index:
$E ++
#If our entry matches our key:
If ($entry -like "*"+$key+"*") {
#add a blank entry to our log:
[string[]]$review += ""
#If we didn't detect our key error(s) or success in the last loop:
If (($AttemptCount -gt $terminalLoop) -and ($AttemptCount -gt $Successloop) -and ($terminalLoop -ne $null)) {
#Stamp a string based on error count:
[string[]]$review += "-=-=-=-=-=-=Didn't find terminal 'KEY' error before next setup attempt here are the last $ErrorCount errors observed-=-=-=-="
#Stage a search string for log review:
$SearchString = $Character+$AttemptCount+$Character+"*"
#Add the last number of errors desired to our log file and continue flow if the entry matches our key
[string[]]$review += $ErrorTable | ? {$_ -like $SearchString} | Select -Last $ErrorCount}
#Increment variable of attempt count by 1
$AttemptCount ++
#Add blank string to log for line break:
[string[]]$review += ""
#Stage speacial string for entry
$SpecialString = "NewInstance"
#Stage the entire string for loop count, special string, and log entry:
[string]$temp = $Character+$attemptcount+$Character+"|"+$Character+$SpecialString+$Character+"|"+$entry.line
#Add the entry to the log file:
[string[]]$review +=$temp
#Notify host that a new install attempt was detected
Write-host "Found attempt" $entry.line}
#If entry matches one of our timeline strings:
If ($entry -match ('(' + [string]::Join(')|(', $TimelineStrings) + ')')) {
#Stage special string:
$SpecialString = "TimeLine"
#Stage the entire string for loop count, special string, and log entry:
[string]$temp = $Character+$attemptcount+$Character+"|"+$Character+$SpecialString+$Character+"|"+$entry.line
#Add the entry to the log file:
[string[]]$Review += $temp}
#If entry matches one of our status strings:
If ($entry -match ('(' + [string]::Join(')|(', $StatusStrings) + ')')) {
#Stage variable for special string
$SpecialString = "Status"
#Stage the entire string for loop count, special string, and log entry:
[string]$temp = $Character+$attemptcount+$Character+"|"+$Character+$SpecialString+$Character+"|"+$entry.line
#Add the entry to the log file:
[string[]]$Review += $temp}
#If entry matches one of our error strings:
If (($entry -match ('(' + [string]::Join(')|(', $Failstrings) + ')'))) {
#Stage variable for special string
$SpecialString = "Error"
#Stage the entire string for loop count, special string, and log entry:
[string]$temp = $Character+$attemptcount+$Character+"|"+$Character+$SpecialString+$Character+"|"+$entry.line
#If entry doesn't match our ignore strings, add it to the errors table:
If ($entry -notmatch ('(' + [string]::Join(')|(', $IgnoreStrings) + ')')){
#Add the entry to the log file:
[string[]]$ErrorTable += $temp}}
#if entry is our key error
If ($Entry -match ('(' + [string]::Join(')|(', $KeyFail) + ')')) {
#Save the loop count
[int]$terminalLoop = $AttemptCount
#Determine what is the current error count
[int]$targetError = $ErrorTable.count
#Add blank string to log for line break:
[string[]]$review += ""
$terminalerror = $entry.line
#Add a special entry in the log:
[string[]]$Review += "-=-=-=-=-= Setup has encountered a hard termination!
$terminalerror
Here are the $ErrorCount leading errors prior to termination in this attempt -=-=-=-=-=
"
#Stage search string
$SearchString = $Character+$AttemptCount+$Character+"*"
#Add the user specified amount of errors in this setup attempt to the log:
[string[]]$Review += $ErrorTable | ? {$_ -like $SearchString} | Select -Last $ErrorCount
#Determine where we are in the focused logs:
$Rawstart = $e - $rawstringscount
#add an entry to log if we specified raw lines:
If ($RawStringonTermination -eq $true) {
[String[]]$review += "=-=-=-=-Here are the last $RawStringscount entries in the log leading to termination-=-=-=-=-=
"
#Add the specified range to the review
[string[]]$Review += $FocusedExchLog.Line[$rawstart..$e]}
}
#If entry is our key success:
If ($entry -match ('(' + [string]::Join(')|(', $SuccessStrings) + ')')) {
#Stage special string:
$SpecialString = "Success!"
#Stage the entire string for loop count, special string, and log entry:
[string]$temp = $Character+$attemptcount+$Character+"|"+$Character+$SpecialString+$Character+"|"+$entry.line
#Add the entry to the log file:
[string[]]$Review += $temp
$Successloop = $AttemptCount
}
}
#Stage search string
$SearchString = $Character+$AttemptCount+$Character+"*"
#If we didn't find the hard exception on the last setup log... add special entry & the user specified number of errors in the error table that match the search string:
If (($AttemptCount -gt $terminalLoop) -and ($AttemptCount -gt $Successloop) -and ($terminalLoop -ne $null) -and ($Successloop -ne $null)) {[string[]]$review += "-=-=-=-=-= The last attempt of the server errors!!!-=-=-=-=" ; [string[]]$review += $ErrorTable |? {$_ -like $SearchString} | select -Last $ErrorCount}
#If export log, set global variable called ExchSetupLog
If ($ExportLogtoShell -eq $true) {[String[]]$Global:ExchSetupLog = $review}
#If Export Directory, export the log into a CSV:
If ($ExportLogToLog -eq $true) {$time = (Get-Date -format hh_mm_ss) ; $Exportlog = $ExportPath + "\ExchangeSetupLogTimeline" +$time + ".log" ; $review | Out-File $Exportlog}
#Let us know how many setup attempts were found
Write-Host "There were $IndexHits attempts in total in this log, we are have the timeline highlight of the last $AttemptCount in the specified location(s)" -ForegroundColor Yellow
#If live review pump results into a |MORE
If ($LiveReview -eq $true) {$Review | More}
}