13
13
#public
14
14
15
15
.CHANGELOG
16
+ 17.07.25 SAN Big cleanup of bug fixes for the dcdiag function, fixes of error codes, output in stderr of all errors for readability
17
+
18
+ .TODO
19
+ Do a breakdown at the top of the output for easy read with ok/ko returns from functions
16
20
17
21
#>
18
22
19
23
# Initialize exit code
20
- $exitCode = 0
24
+ $global : exitCode = 0
21
25
22
26
# Function to perform Active Directory tests
23
27
function CheckAD {
24
28
[CmdletBinding ()]
25
29
param (
26
- [Parameter (Mandatory = $true , ValueFromPipeline = $true , ValueFromPipelineByPropertyName = $true )]
27
- [string []]$Tests
30
+ [Parameter (Mandatory = $true , ValueFromPipeline = $true , ValueFromPipelineByPropertyName = $true )]
31
+ [string []]$Tests ,
32
+
33
+ [Parameter ()]
34
+ [hashtable ]$SuccessPatterns = @ {
35
+ ' en' = @ (' passed test' )
36
+ ' fr' = @ (' a réussi' , ' a reussi' , ' a russi' , ' ussi' )
37
+ },
38
+
39
+ [Parameter ()]
40
+ [int ]$MinimumMatches = 2
28
41
)
29
42
30
- process {
31
- $results = @ {}
43
+ $DebugMode = $false
44
+ $ global :exitCode = 0
32
45
33
- foreach ($test in $Tests ) {
34
- $output = dcdiag / test:$test
46
+ # Combine all success patterns from all languages into a single list
47
+ $allPatterns = @ ()
48
+ foreach ($lang in $SuccessPatterns.Keys ) {
49
+ $allPatterns += $SuccessPatterns [$lang ]
50
+ }
35
51
36
- if ($output -notmatch " chou" ) {
37
- $results [$test ] = " OK"
38
- } else {
39
- $results [$test ] = " Failed!"
40
- $global :exitCode ++
52
+ if ($DebugMode ) {
53
+ Write-Host " `n [DEBUG] Loaded Success Patterns:"
54
+ foreach ($p in $allPatterns ) {
55
+ Write-Host " - $p "
56
+ }
57
+ Write-Host " "
58
+ }
59
+
60
+ $results = @ {}
61
+
62
+ foreach ($test in $Tests ) {
63
+ Write-Host " `n Running DCDIAG test: $test "
64
+
65
+ # Start dcdiag process and redirect output
66
+ $startInfo = New-Object System.Diagnostics.ProcessStartInfo
67
+ $startInfo.FileName = " dcdiag.exe"
68
+ $startInfo.Arguments = " /test:$test "
69
+ $startInfo.RedirectStandardOutput = $true
70
+ $startInfo.RedirectStandardError = $true
71
+ $startInfo.UseShellExecute = $false
72
+ $startInfo.CreateNoWindow = $true
73
+ $process = New-Object System.Diagnostics.Process
74
+ $process.StartInfo = $startInfo
75
+ $process.Start () | Out-Null
76
+ $stream = $process.StandardOutput.BaseStream
77
+ $memoryStream = New-Object System.IO.MemoryStream
78
+ $buffer = New-Object byte[] 4096
79
+ while (($read = $stream.Read ($buffer , 0 , $buffer.Length )) -gt 0 ) {
80
+ $memoryStream.Write ($buffer , 0 , $read )
81
+ }
82
+ $process.WaitForExit ()
83
+
84
+ $bytes = $memoryStream.ToArray ()
85
+ $output = [System.Text.Encoding ]::GetEncoding(1252 ).GetString($bytes )
86
+
87
+ if ($DebugMode ) {
88
+ $preview = if ($output.Length -gt 800 ) { $output.Substring (0 , 800 ) + " `n ..." } else { $output }
89
+ Write-Host " [DEBUG] DCDIAG Output Preview:"
90
+ Write-Host $preview
91
+ Write-Host " "
92
+ }
93
+
94
+ $matchCount = 0
95
+ foreach ($pattern in $allPatterns ) {
96
+ $count = ([regex ]::Matches($output , [regex ]::Escape($pattern ))).Count
97
+ $matchCount += $count
98
+
99
+ if ($DebugMode ) {
100
+ Write-Host " [DEBUG] Pattern '$pattern ' matched $count time(s)."
41
101
}
102
+ }
103
+
104
+ if ($DebugMode ) {
105
+ Write-Host " [DEBUG] Total success match count: $matchCount `n "
106
+ }
42
107
43
- # Output individual test result
44
- Write-Host " DCDIAG Test: $test Result: $ ( $results [$test ]) "
108
+ if ($matchCount -ge $MinimumMatches ) {
109
+ $results [$test ] = " OK"
110
+ } else {
111
+ $results [$test ] = " Failed!"
112
+ Write-Error " $results [$test ] = Failed!"
113
+ $global :exitCode ++
45
114
}
46
115
47
- $ results
116
+ Write-Host " DCDIAG Test: $test Result: $ ( $ results[ $test ] ) "
48
117
}
118
+
119
+ return $results
49
120
}
50
121
51
122
# Function to compare GPO version numbers
52
-
53
123
function Compare-GPOVersions {
54
124
[CmdletBinding ()]
55
125
param ()
@@ -72,34 +142,36 @@ function Compare-GPOVersions {
72
142
73
143
# USER - Compare version numbers
74
144
if ($NumUserSysvol -ne $NumUserAD ) {
75
- Write-Host " $GPOName ($GPOId ) : USER Versions différentes (Sysvol : $NumUserSysvol | AD : $NumUserAD )" - ForegroundColor Red
145
+ Write-Host " $GPOName ($GPOId ) : USER Versions différentes (Sysvol : $NumUserSysvol | AD : $NumUserAD )"
146
+ Write-Error " $GPOName ($GPOId ) : USER Versions différentes (Sysvol : $NumUserSysvol | AD : $NumUserAD )"
76
147
$global :exitCode ++
77
148
} else {
78
- Write-Host " $GPOName : USER Versions identiques" - ForegroundColor Green
149
+ Write-Host " $GPOName : USER Versions identiques"
79
150
}
80
151
81
152
# COMPUTER - Compare version numbers
82
- if ($NumComputerSysvol -ne $NumComputerAD ) {
83
- Write-Host " $GPOName ($GPOId ) : COMPUTER Versions différentes (Sysvol : $NumComputerSysvol | AD : $NumComputerAD )" - ForegroundColor Red
153
+ if ($NumComputerSysvol -ne $NumComputerAD ) {Health
154
+ Write-Host " $GPOName ($GPOId ) : COMPUTER Versions différentes (Sysvol : $NumComputerSysvol | AD : $NumComputerAD )"
155
+ Write-Error " $GPOName ($GPOId ) : COMPUTER Versions différentes (Sysvol : $NumComputerSysvol | AD : $NumComputerAD )"
84
156
$global :exitCode ++
85
157
} else {
86
- Write-Host " $GPOName : COMPUTER Versions identiques" - ForegroundColor Green
158
+ Write-Host " $GPOName : COMPUTER Versions identiques"
87
159
}
88
160
}
89
- Write-Host " GPO USER/COMPUTER Version OK" - ForegroundColor Green
161
+ Write-Host " GPO USER/COMPUTER Version OK"
90
162
}
91
163
}
92
164
93
165
# Function to check if the Recycle Bin in enabled
94
-
95
166
function Check-ADRecycleBin {
96
167
$recycleFeatures = Get-ADOptionalFeature - Filter {name -like " recycle bin feature" }
97
168
98
169
foreach ($feature in $recycleFeatures ) {
99
170
if ($null -ne $feature.EnabledScopes ) {
100
- Write-Output " OK: Recycle Bin enabled"
171
+ Write-Host " OK: Recycle Bin enabled"
101
172
} else {
102
- Write-Output " KO: Recycle Bin disabled"
173
+ Write-Host " KO: Recycle Bin disabled"
174
+ Write-Error " KO: Recycle Bin disabled"
103
175
$global :exitCode ++
104
176
}
105
177
}
@@ -110,31 +182,29 @@ try {
110
182
$adFeature = Get-WindowsFeature - Name AD- Domain- Services - ErrorAction Stop
111
183
112
184
if ($adFeature.InstallState -eq " Installed" ) {
113
- # Specify your AD tests
185
+
186
+ # function with the AD tests
114
187
$tests = (" Advertising" , " FrsSysVol" , " MachineAccount" , " Replications" , " RidManager" , " Services" , " FsmoCheck" , " SysVolCheck" )
115
- # Call the function with the AD tests
116
- Write-Host " DCDIAG"
188
+ Write-Host " DCDIAG tests: $tests "
117
189
$testResults = CheckAD - Tests $tests
118
-
119
190
$failedTests = $testResults.GetEnumerator () | Where-Object { $_.Value -eq " Failed!" }
120
-
121
191
if ($failedTests ) {
122
192
Write-Error " Some Active Directory tests failed."
123
- $failedTests | ForEach-Object { Write-Error " $ ( $_.Key ) test failed." }
124
- $global :exitCode += $failedTests.Count
125
193
} else {
126
194
Write-Host " All Active Directory tests passed successfully."
127
195
}
128
196
Write-Host " "
197
+
198
+ # function to compare GPO versions
129
199
Write-Host " GPO Versions checks"
130
- # Call the function to compare GPO versions
131
200
Compare-GPOVersions
132
-
133
201
Write-Host " "
202
+
203
+ # function to check the Recycle Bin
134
204
Write-Host " Recycle Bin checks"
135
- # Call the function to check the Recycle Bin
136
205
Check- ADRecycleBin
137
-
206
+ Write-Host " "
207
+
138
208
} else {
139
209
Write-Host " Active Directory Domain Services feature is not installed or not in the 'Installed' state."
140
210
exit
@@ -144,4 +214,5 @@ try {
144
214
$global :exitCode ++
145
215
}
146
216
147
- exit $exitCode
217
+ $host.SetShouldExit ($global :exitCode )
218
+ exit $global :exitCode
0 commit comments