Montag, 23. April 2018

Schülerordner Links erstellen

Über Freigaben --> Home-Verzeichnisse Schueler --> _klassen können Lehrer die Ordner der Schühler ihrer Klassen anklicken. Da diese jedoch Links auf Linuxbasis sind können diese nicht kopiert werden.

Um eine "Windows Kopie" des Ordners "_klassen" anzulegen habe ich ein kleines Powershell Skript geschrieben. Es erstellt die gleiche Ordnerstruktur des Ordners "_klassen", ändert jedoch die Links zu den Schülerverzeichnissen zu Windows Links. Der neue Ordner liegt laut Skript auf c:\klassen. Er könnte als Alternative mit zwei Unterstrichen als "__klassen" in den Ordner der Schülerverzeichnisse gelegt werden. Dann kann sich jeder Kollege die Links seiner Klasse auch herauskopieren. 


Hier das (einfache) Skript
$a = Get-ChildItem -Path '\\server\Home-Verzeichnisse Schueler\_klassen\'
foreach ($as in $a){
    $b = Get-ChildItem -Path ('\\server\Home-Verzeichnisse Schueler\_klassen\' + $as.Name)
    New-Item -ItemType directory -Path ("c:\klassen\"+$as.Name)
    foreach ($bs in $b){
        write-host $bs.Name
        $WshShell = New-Object -comObject WScript.Shell
        $Shortcut = $WshShell.CreateShortcut("c:\klassen\"+$as.Name+"\"+$bs.Name+".lnk")
        $Shortcut.TargetPath = ("\\server\Home-Verzeichnisse Schueler\"+$bs.Name)
        $Shortcut.Save()
    }
}
Das vorige Skript ließt den Ordner _klassen aus und erstellt eine Kopie mit Windows Links.
Es ist aber auch möglich alle Informationen direkt aus dem LDAP Verzeichnis zu lesen. Das Skript wird dadurch etwas Komplizierter, legt jedoch z.B. auch wirklich nur Klassen an, nicht auch von lehrern angelegte Gruppen.

$speicherpfad="c:\klassen\"
[ADSI]$domain = "LDAP://CN=klassen, CN=schueler,CN=groups,OU=schule, DC=paedml-linux,DC=lokal"
$klassen = $domain.Children.distinguishedName | ForEach-Object {[ADSI]"LDAP://$_"}
New-Item -force -ItemType directory -Path ($speicherpfad)
foreach($k in $klassen){
    New-Item -force -ItemType directory -Path ($speicherpfad + $k.Name.Replace("schule-", ""))
    $schueler = $k.Member | ForEach-Object {[ADSI]"LDAP://$_"}
    foreach($s in $schueler){
        if($s.memberOf[0].Contains("schueler")){
            $WshShell = New-Object -comObject WScript.Shell
            $Shortcut = $WshShell.CreateShortcut("c:\klassen\"+$k.Name.Replace("schule-", "")+"\"+$s.displayName+".lnk")
            $Shortcut.TargetPath = ("\\server\"+$s.Name)
            $Shortcut.Save()
        }
    }
}
Damit Dateien und Ordner, welche nicht(mehr) benötigt werden, entfernt werden, kann das Skript den jeweiligen Ordner Inhalt auslesen. Falls die Dateien keine Entsprechungen im LDAP finden können Sie gelöscht werden. Das Skript wird dadurch um einiges länger, der "klassen" Ordner ist dadurch aber immer aktuell und ein Abbild der LDAP Struktur, gelöschte Klassen oder Schüler-Links werden entfernt usw.
$speicherpfad="\\server\Home-Verzeichnisse Schueler\__klassen\"
Write-Host "Zielordner ist " $speicherpfad
$start = (Get-Date)
[ADSI]$domain = "LDAP://CN=klassen, CN=schueler,CN=groups,OU=schule, DC=paedml-linux,DC=lokal"
$klassen = $domain.Children.distinguishedName | ForEach-Object {[ADSI]"LDAP://$_"}
#Alle Dateien und Ordner im Speicherpfad bekommen das Attribut Entfernen=$true. Wenn der Ordner existieren muss wird es später wieder auf $false gesetzt.
$alteOrdner = Get-ChildItem -Path ($speicherpfad)
$alteOrdner | Add-Member -NotePropertyName Entfernen -NotePropertyValue $true
$maxi = $alteOrdner|measure
New-Item -force -ItemType directory -Path ($speicherpfad) | Out-Null
$zaehler=0
foreach($k in $klassen){
 
    #Fortschrittsanzeige, falls unerwünscht, mit # auskommentieren.
    $zaehler=$zaehler+1
    write-host ([math]::round(($zaehler/($klassen.Count)*100),0))"%"
 
    #Für jeden existierenden Ordner wird geprüft, ob es eine Klasse mit dem gleichen Namen gibt. Falls nicht bleibt das Attribut Entfernen auf $true.
    for ($i=0;$i -lt $maxi.Count; $i++){
        if($k.Name.Replace("schule-", "") -like $alteOrdner[$i] ){ 
            $alteOrdner[$i].Entfernen = $false 
        }
    }
    New-Item -force -ItemType directory -Path ($speicherpfad + $k.Name.Replace("schule-", "")) | Out-Null
 
    # $zwischenspeicher enthält alle Dateien des jeweiligen Klassenordners
    $zwischenspeicher = Get-ChildItem -Path ($speicherpfad + $k.Name.Replace("schule-", ""))
    # Für jede Datei wird das Attribut Entfernen auf $true gesetzt
    $zwischenspeicher  | Add-Member -NotePropertyName Entfernen -NotePropertyValue $true
 
    $schueler = $k.Member | ForEach-Object {[ADSI]"LDAP://$_"}
    foreach($s in $schueler){
        if($s.memberOf[0].Contains("schueler")){
            $WshShell = New-Object -comObject WScript.Shell
            $Shortcut = $WshShell.CreateShortcut($speicherpfad+$k.Name.Replace("schule-", "")+"\"+$s.displayName+".lnk")
            $Shortcut.TargetPath = ("\\server\Home-Verzeichnisse Schueler\"+$s.Name)
            $Shortcut.Save()
        }
        $max = $zwischenspeicher |measure
        #Falls die Datei durch LDAP bestätigt wurde wird Entfernen = $false
        for ($i=0;$i -lt $max.Count; $i++) {
                if($zwischenspeicher[$i].baseName -like $s.displayName){
                    $zwischenspeicher[$i].Entfernen = $false;
                }
        }
    }
    #Dateien mit Entfernen = $true löschen.
    #Links zu Schülerordnern, welche nichtmehr in der LDAP Gruppe der Klasse vorhanden sind.
    foreach($z in $zwischenspeicher){
        if($z.Entfernen){
            Remove-Item -Path ($z.FullName) -Recurse -force
        }
    }
}
#Ordner mit Entfernen=$true löschen.
foreach($o in $alteOrdner){
    if($o.Entfernen){
             Remove-Item -Path $o.FullName -Recurse -force
    }
}
#Leere Ordner löschen
Get-ChildItem -Path $speicherpfad -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse
$Ende = (Get-Date)
write-host "Das Sript lief für" ([math]::round(($ende - $start).TotalSeconds,0))"Sekunden"

(Erinnerung aus dem Shutdown-Aktikel) Skript Zeit-gesteuert ausführen

Zum zeit-gesteuerten Ausführen öffnen Sie die AdminVM, drücken Sie die Windows-taste und geben Sie "Aufgabenplanung" ein.
Klicken Sie auf "Aufgabe erstellen..." und geben Sie der Aufgabe einen Namen, z.B. "Schulcomputer herunterfahren".
Wählen Sie den Reiter "Trigger" und klicken Sie auf "Neu" und legen Sie hier Ihren Zeiplan an.
Stellen Sie eine Startzeit ein, z.B. 8:00:00 und Täglich. Klicken Sie auf "Wiederholen jede: " und stellen Sie 30 Minuten für die Dauer von 12 Stunden ein.Klicken Sie nun auf OK.
Im Reiter "Aktionen" klicken Sie auf "Neu". Die Aktion "Programm starten" ist voreingestellt. Bei Programm Tragen Sie "Powershell.exe" ein. Bei Parametern Tragen Sie
-ExecutionPolicy Bypass h:\PFAD\meinSkript.ps
ein. Mit einem Klick auf OK sollte das Skript nun täglich alle 30 Minuten ausgeführt werden.
Quelle

Montag, 16. April 2018

Opsi Statusfenster ausschalten.

Standardmäßig erscheint nach jeder Benutzeranmeldung ein kleines Opsi Fenster. In manchen Fällen schließt sich dieses erst relativ spät. Außerdem hat dieses Fenster unangenehme Eigenschaften, z.B. wenn man die Bildschirmauflösung ändert.
Hier möchte ich beschreiben, wie man das Fenster ausblenden kann.

Standardtwert setzen

Als erstes muss der Standartwert für das Ausblenden gesetzt werden.
Nach den öffnen von "Opsi-Configed Local" klicken Sie auf Server-Konfiguration.


Klicken Sie dann auf "Host-Parameter" --> "opsiclientd". Dort klicken Sie auf den Schlüssel "opsiclientd.event.user_login.active" und setzen den Wert auf "false". Bestätigen Sie dies mit einem Klick auf das rote Häkchen. Nun ist der Wert für alle neuen Clients gesetzt und wirksam.
Klicken Sie auf den linken Knopf neben der Server-Konfiguration um zur normalen Übersicht (der Client-Konfiguration) zurück zu kommen.

Werte für vorhandene Clients setzen


Wenn Sie bereits Clients ausgerollt haben müssen Sie den Wert für diese nochmals von Hand setzen.
Markieren Sie die Clients. Auf der rechten Seite finden Sie neben den Reitern "Produktkonfiguration" und "Netboot-Produkte" auch den Reiter "Host-Parameter". Klicken Sie auf "Host-Parameter" --> "opsiclientd". Dort klicken Sie auf den Schlüssel "opsiclientd.event.user_login.active" und setzen den Wert auf "false". Bestätigen Sie dies mit einem Klick auf das rote Häkchen.
Nun muss der Opsi-Client neu aufgespiet werden. Klicken Sie auf Produktkonfiguration und setzen Sie "opsi-client-agent" auf "setup".
Nach einem Neustart und der darauf folgenden neuionstallation des Opsi Agenten ist die Änderung nun wirksam.

Mittwoch, 11. April 2018

Tipparbeit sparen: Admin Anmeldung

Einer der ersten Tricks, welche mir von unserem Dienstleister (Danke Michael!!) verraten wurden habe ich so verinnerlicht, dass ich über deren Besonderheit gar nicht mehr nachdachte.

tl;dr


Login Domänenadmin
p\administrator
Login lokaler Admin
.\administrator

Erklärung


Bei der Anmeldung als Domänen Administrator muss man Windows sagen, an welcher Domäne man sich anmeldet (da es auch einen lokalen Admin gibt).

Der Benutzername ist dann:
paedml-linux\administrator
Samba juckt das aber nicht, es akzeptiert fast jede Zeichenfolge als Domänen-Admin, z.B.
p\administrator
Natürlich geht auch
ichwillnachhause\administrator
paedml-murmelbahn\administrator :) 

Umgekehrt möchte man sich manchmal auch als lokaler Administrator anmelden. Dazu muss man als Domäne die Bezeichnung des PCs eingeben.
computer16\administrator
Da der Computername zum Zeitpunkt der Anmeldung nicht angezeigt wird, kann das etwas anstrengend sein. Aber dafür hat Windows eine eigene Abkürzung eingebaut, die Unabhängig von der paedML an jedem Windows-Domänen PC funktioniert.
.\administrator
meldet sich am lokalen Gerät an, der Name dieses Gerätes wird dann freundlicherweise sogar eingeblendet