Wenn man im SCCM 2012 (R2) eine TaskSequenz laufen lässt, bricht diese normalerweise ab, sobald ein einzelner Step fehlerhaft ist. Um aber gerade bei längeren Tasksequenzen einen Abbruch (evtl. kurz vor Fertigstellung) zu vermeiden, kann man einzelne (oder auch alle) Schritte so konfigurieren, dass bei deren Fehler dennoch regulär weitergearbeitet wird:
Wenn man nun diese Option wählt, kann es einem leicht passieren, dass man bei Fertigstellung einer Tasksequenz nicht sofort sieht, ob alle Schritte erfolgreich abgearbeitet wurden oder eben einzelne Schritte einen Fehler verursacht haben. Um diese leichter abprüfen zu können, habe ich ein kleines PowerShell-Skript geschrieben. Dieses erhebt nicht den Anspruch, aus Programmierer-Sicht optimal geschrieben zu sein, sondern es soll in erster Linie funktionieren. Und das tut es (zumindest in unserer Produktiv-Umgebung) sehr gut ;-)
Hier nun das Skript-Listing (und hier als .ps1 zum Download):
cls$failed=New-ObjectSystem.Collections.ArrayList$success=New-ObjectSystem.Collections.ArrayList$logfiles=New-ObjectSystem.Collections.ArrayList$logdirs=New-ObjectSystem.Collections.ArrayList$notfound=0$tsfailed=$false$logdirs+='C:\Windows\ccm\logs'$logdirs+='C:\Windows\ccm\logs\smstslog'$logdirs+='c:\_SMSTaskSequence\Logs\Smstslog\'$logdirs+='c:\windows\system32\ccm\logs\Smstslog\'$logdirs+='c:\windows\system32\ccm\logs\'$logdirs+='c:\windows\sysWOW64\ccm\logs\'foreach($logdirin$logdirs){If(Test-Path$logdir){$foundlogfiles=Get-ChildItem$logdir-Filtersmsts*.logforeach($foundlogfilein$foundlogfiles){$logfiles+=$foundlogfile.FullName}}}foreach($filein$logfiles){Write-Host'Parsing Logile'$file$logzeilen=Select-String-Path$file-Pattern'Failed to run the action:'foreach($zeilein$logzeilen){$zeile=$zeile.ToString()$pos1=$zeile.IndexOf('Failed to run the action:')$pos2=$zeile.IndexOf(')]LOG]!>')if($pos2-le$pos1){$pos2=$zeile.Length}$Paket=$zeile.Substring($pos1+26,$pos2-($pos1+26))$failed+=$Paket$notfound++}}foreach($filein$logfiles){$logzeilen=Select-String-Path$file-Pattern'Successfully completed the action'foreach($zeilein$logzeilen){$zeile=$zeile.ToString()$pos1=$zeile.IndexOf('Successfully completed the action (')$pos2=$zeile.IndexOf(') with the exit')$Paket=$zeile.Substring($pos1+35,$pos2-($pos1+35))$success+=$Paket}}foreach($filein$logfiles){$logzeilen=Select-String-Path$file-Pattern'Execution of task sequence failed'if($logzeilen.Count-gt0){$tsfailed=$true}}if($tsfailed){Write-Host-ForegroundcolorRed'The whole TaskSequence failed to run!'}if($notfound-gt0){Write-Host-ForegroundColorYellow'At least one action failed. TaskSequence possibly aborted!'Write-Host-ForegroundColorRed'Failed actions:'foreach($pakin$failed){Write-Host$pak}}Write-Host-ForegroundColorGreen'Successfully completed actions:'foreach($pakin$success){Write-Host$pak}if($notfound-gt0){Write-Host-ForegroundColorYellow'At least one action failed. TaskSequence possibly aborted!'}Read-Host"Done - press any key to continue ..."
Ausgabe sieht dann in etwa so aus: