1313 #public
1414
1515.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
1620
1721#>
1822
1923# Initialize exit code
20- $exitCode = 0
24+ $global : exitCode = 0
2125
2226# Function to perform Active Directory tests
2327function CheckAD {
2428 [CmdletBinding ()]
2529 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
2841 )
2942
30- process {
31- $results = @ {}
43+ $DebugMode = $false
44+ $ global :exitCode = 0
3245
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+ }
3551
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)."
41101 }
102+ }
103+
104+ if ($DebugMode ) {
105+ Write-Host " [DEBUG] Total success match count: $matchCount `n "
106+ }
42107
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 ++
45114 }
46115
47- $ results
116+ Write-Host " DCDIAG Test: $test Result: $ ( $ results[ $test ] ) "
48117 }
118+
119+ return $results
49120}
50121
51122# Function to compare GPO version numbers
52-
53123function Compare-GPOVersions {
54124 [CmdletBinding ()]
55125 param ()
@@ -72,34 +142,36 @@ function Compare-GPOVersions {
72142
73143 # USER - Compare version numbers
74144 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 )"
76147 $global :exitCode ++
77148 } else {
78- Write-Host " $GPOName : USER Versions identiques" - ForegroundColor Green
149+ Write-Host " $GPOName : USER Versions identiques"
79150 }
80151
81152 # 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 )"
84156 $global :exitCode ++
85157 } else {
86- Write-Host " $GPOName : COMPUTER Versions identiques" - ForegroundColor Green
158+ Write-Host " $GPOName : COMPUTER Versions identiques"
87159 }
88160 }
89- Write-Host " GPO USER/COMPUTER Version OK" - ForegroundColor Green
161+ Write-Host " GPO USER/COMPUTER Version OK"
90162 }
91163}
92164
93165# Function to check if the Recycle Bin in enabled
94-
95166function Check-ADRecycleBin {
96167 $recycleFeatures = Get-ADOptionalFeature - Filter {name -like " recycle bin feature" }
97168
98169 foreach ($feature in $recycleFeatures ) {
99170 if ($null -ne $feature.EnabledScopes ) {
100- Write-Output " OK: Recycle Bin enabled"
171+ Write-Host " OK: Recycle Bin enabled"
101172 } else {
102- Write-Output " KO: Recycle Bin disabled"
173+ Write-Host " KO: Recycle Bin disabled"
174+ Write-Error " KO: Recycle Bin disabled"
103175 $global :exitCode ++
104176 }
105177 }
@@ -110,31 +182,29 @@ try {
110182 $adFeature = Get-WindowsFeature - Name AD- Domain- Services - ErrorAction Stop
111183
112184 if ($adFeature.InstallState -eq " Installed" ) {
113- # Specify your AD tests
185+
186+ # function with the AD tests
114187 $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 "
117189 $testResults = CheckAD - Tests $tests
118-
119190 $failedTests = $testResults.GetEnumerator () | Where-Object { $_.Value -eq " Failed!" }
120-
121191 if ($failedTests ) {
122192 Write-Error " Some Active Directory tests failed."
123- $failedTests | ForEach-Object { Write-Error " $ ( $_.Key ) test failed." }
124- $global :exitCode += $failedTests.Count
125193 } else {
126194 Write-Host " All Active Directory tests passed successfully."
127195 }
128196 Write-Host " "
197+
198+ # function to compare GPO versions
129199 Write-Host " GPO Versions checks"
130- # Call the function to compare GPO versions
131200 Compare-GPOVersions
132-
133201 Write-Host " "
202+
203+ # function to check the Recycle Bin
134204 Write-Host " Recycle Bin checks"
135- # Call the function to check the Recycle Bin
136205 Check- ADRecycleBin
137-
206+ Write-Host " "
207+
138208 } else {
139209 Write-Host " Active Directory Domain Services feature is not installed or not in the 'Installed' state."
140210 exit
@@ -144,4 +214,5 @@ try {
144214 $global :exitCode ++
145215}
146216
147- exit $exitCode
217+ $host.SetShouldExit ($global :exitCode )
218+ exit $global :exitCode
0 commit comments