Haikos Blog Blog von Haiko Hertes zu allen Themen rund um Microsoft und Datacenter

28Jan/140

Windows Server 2012 (R2): Wie man das „Tools“-Menü im Servermanager anpasst

Microsoft Premier Field Engineer Michael Hildebrand beschreibt in seinem Blog, wie man die Tools-Leiste oben rechts im Servermanager anpassen und um weitere Einträge ergänzen kann:

http://blogs.technet.com/b/askpfeplat/archive/2014/01/27/how-to-customize-server-manager-in-windows-server-2012-and-2012-r2-get-creative.aspx

Kern des Ganzen ist der Ordner "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\"

Dort kann man entsprechende Verknüpfungen ablegen:

Toolsmenu

Das funktioniert sogar mit Ordnern, um besser strukturieren zu können! Einzig die Icons, die von anderen Systemen abgelegt worden sollte man nicht verändern, weil es sonst u.U. zu Problemen kommt, etwa beim entfernen der jeweiligen Funktion.

 

15Jan/142

SCCM: Laufwerk C:\ auf CAS läuft wegen SCCMContenLib voll

Erst kürzlich bekam ich von unserem SCCM-System eine E-Mail mit folgendem Betreff:

Warnung: Warnung: Nicht genügend Speicherplatz für Datenbank an Standort "CAS" vorhanden

Als ich der Sache auf den Grund ging, stellte ich fest, dass der Ordner C:\SCCMContentLib ziemlich groß geworden ist:

contenlib1

Der Grund hierfür ist, dass auch auf einer CAS – wo kein DP vorhanden ist – Daten für die Verteilung abgelegt werden, wenn dieser Content auf der CAS angelegt wurde, was im Sinne einer zentralen Verteilung sicher oft gemacht wird. Da aber nun kein DP vorhanden ist, kann man das Laufwerk nicht beeinflussen, auf dem diese Daten abgelegt werden sollen. Daher wird standardmäßig das Laufwerk verwendet, welches über den meisten freien Speicherplatz verfügt (zum Zeitpunkt der Installation der CAS).

Dies hätte man verhindern können, wenn man vor der Installation der ContentLibrary auf der CAS ein leeres File mit dem Namen “no_sms_on_drive.sms” im Laufwerks-Root des Laufwerkes ablegt, auf dem keine SCCM-Daten liegen sollen.

Um nun aber nachträglich die Daten von einem Laufwerk auf ein anderes zu bekommen, ist das Tool “ContenLibraryTransfer” gedacht, welches sich im Configuration Manager Toolkit befindet.

Neben diesem Tool sind dort auch noch weitere enthalten:

contenlib2

Hinweis: Es wird immer nur die aktuellste Version von Microsoft angeboten – also aktuell 2012 R2. Diese Version funktioniert auch z.B. auf einem SCCM 2012 SP1!

Die Benutzung ist relativ einfach:

C:\Program Files (x86)\ConfigMgr 2012 Toolkit R2\ServerTools\ContentLibraryTransfer.exe –SourceDrive <AktuellesLaufwerk> –TargetDrive <ZielLaufwerk>

Das Tool kopiert dann die Inhalte auf das Ziellaufwerk und sorgt dafür, dass alle internen Verweise entsprechend geändert werden. Außerdem wird anschließend auf dem Quelllaufwerk eine NO_SMS_ON_DRIVE.SMS angelegt.

Am Ende sollte es dann so aussehen:

contenlib3

14Jan/140

SCCM: PowerShell-Skript, um OSD-Ergebnisse zu parsen

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:

TaskSequenz_BeiFehler

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):

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
cls
$failed = New-Object System.Collections.ArrayList
$success = New-Object System.Collections.ArrayList
$logfiles = New-Object System.Collections.ArrayList
$logdirs = New-Object System.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($logdir in $logdirs)
{
    If (Test-Path $logdir)
    {
        $foundlogfiles = Get-ChildItem $logdir -Filter smsts*.log
        foreach($foundlogfile in $foundlogfiles)
        {
            $logfiles += $foundlogfile.FullName
        }
    }
}
 
foreach ($file in $logfiles)
{
    Write-Host 'Parsing Logile' $file
    $logzeilen = Select-String -Path $file -Pattern 'Failed to run the action:'
    foreach ($zeile in $logzeilen)
    {
        $zeile = $zeile.ToString()
        $pos1 = $zeile.IndexOf('Failed to run the action:')
        $pos2 = $zeile.IndexOf(')]LOG]!&gt;')
        if ($pos2 -le $pos1)
        {
            $pos2 = $zeile.Length
        }
        $Paket = $zeile.Substring($pos1+26,$pos2-($pos1+26))
        $failed += $Paket
        $notfound++
    }
}
 
foreach ($file in $logfiles)
{
    $logzeilen = Select-String -Path $file -Pattern 'Successfully completed the action'
    foreach ($zeile in $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 ($file in $logfiles)
{
    $logzeilen = Select-String -Path $file -Pattern 'Execution of task sequence failed'
    if ($logzeilen.Count -gt 0)
    {
        $tsfailed = $true
    }
}
 
if ($tsfailed)
{
    Write-Host -Foregroundcolor Red 'The whole TaskSequence failed to run!'
}
 
if ($notfound -gt 0)
{
    Write-Host -ForegroundColor Yellow 'At least one action failed. TaskSequence possibly aborted!'
    Write-Host -ForegroundColor Red 'Failed actions:'
    foreach($pak in $failed)
    {
        Write-Host $pak
    }
}
 
Write-Host -ForegroundColor Green 'Successfully completed actions:'
foreach($pak in $success)
{
    Write-Host $pak
}
 
if ($notfound -gt 0)
{
    Write-Host -ForegroundColor Yellow 'At least one action failed. TaskSequence possibly aborted!'
}
 
Read-Host "Done - press any key to continue ..."

Ausgabe sieht dann in etwa so aus:

Output