Neues Jahr, neues Design

Vor über 5 Jahren begonnen, nun endlich auf der produktiven Seite aktiv.

2018

Nach 6 Jahren mit dem alten Website-Design entschied ich mich für eine Modernisierung. Obwohl ich alternative CMS-Optionen prüfte, entschied ich mich gegen einen Wechsel, da der Umstieg mehr Zeit in Anspruch genommen hätte und es beim Funktionsumfang, insbesondere für Fotos und Galerien und Rückschritt gewesen wäre. WordPress blieb als Unterbau, und die Wahl des Themes wurde entscheidend.

Trotz meiner begrenzten Erfahrung im Webdesign, die aus meiner Informatik-Ausbildung und dem Betrieb der Webseite stammt, strebte ich ein kompaktes Theme an, um die Ladezeiten gering zu halten. Der Inhalt der Seite würde schon genug dazu beitragen.

Framework-Themes wurden ausgeschlossen, da sie zwar einfache Anpassungen ermöglichen, jedoch oft gross und schwerfällig sind.

Die Option, ein vollständig selbst geschriebenes Theme zu erstellen, wurde aufgrund mangelnder Erfahrung und geringem Interesse am Coden verworfen.

Stattdessen entschied ich mich für ein Theme, das meinen Vorstellungen nahe kam, und führte Anpassungen in einem Child Theme durch, was sich bereits beim alten Design bewährt hatte. Dies ermöglichte eine effiziente Anpassung des Designs, das nur selten geändert wurde, und hielt die Ladezeiten akzeptabel.

Die Auswahl eines vielversprechenden Themes war schnell erledigt, und die ersten Anpassungen im Menü und eigenem CSS waren problemlos. Bei strukturellen Anpassungen stiess ich jedoch auf Schwierigkeiten mit dem Child Theme-Ansatz. Der Aufbau moderner  Themes erlaubte nur Anpassungen an vorgesehenen Stellen im Haupttheme. Das erforderte mehr Zeit für Anpassungen am Haupttheme und das Nachverfolgen der Änderungen für zukünftige Updates.

Da zu dieser Zeit noch eine berufliche Veränderung anstand, hatte ich das Projekt erstmal auf Eis gelegt. Dies war im Jahr 2018.

2023

Weitere 5 Jahre später, mit einer weiteren beruflichen Veränderung, diesmal Richtung Selbstständigkeit, wurde es langsam Zeit das neue Design zu finalisieren. Das Ende von PHP 7.x und Probleme mit dem alten Design unter PHP 8.x verstärkten die Dringlichkeit. Das Redesign wurde wieder aufgegriffen und um die Änderungen im Haupttheme zu verfolgen das Plugin Gitium eingeführt. Damit werden Änderungen auf Github hochgeladen und eine Versionierung ermöglicht. Damit war auch der Weg für die letzten Anpassungen frei und ich konnte das Design vervollständigen.

Nach der Überarbeitung des Frontends wurde das Backend optimiert und die Plugins einer gründlichen Aufräumaktion unterzogen. Einige veraltete Plugins, die keine Updates mehr erhielten und Schwierigkeiten verursachten, wurden entfernt. Neue Plugins, die durch das aktualisierte Theme hinzugekommen waren und dabei ähnliche Funktionen wie bestehende erfüllten, wurden ebenfalls überprüft. Zudem wurden nicht mehr benötigte Plugins aussortiert, da die entsprechenden Funktionen mittlerweile in WordPress integriert waren. Diese Bereinigungsmassnahmen zielen darauf ab, die Website schlank zu halten. Dies führt zu kürzeren Ladezeiten, einer insgesamt besseren Performance und reduziert gleichzeitig potenzielle Angriffsflächen für Sicherheitslücken.

Obwohl noch einige kleinere Anpassungen ausstehen, wie beispielsweise die Optimierung der Bilddarstellung im Bereich Planespotting, habe ich mich dennoch dazu entschieden, das neue Design live zu schalten. Dieser Schritt markiert einen Fortschritt und verhindert, dass das Projekt weiter aufgeschoben wird.

Rename Files

Ursprünglich als Test gedacht, habe ich es zum Umbenennen meiner Mediensammlung eingesetzt. Ein Script zum Auslesen und die Daten in eine CSV-Datei schreiben, ein Script zum Einlesen der geänderten CSV-Datei und umbenennen der Dateien. Dazwischen Excel zur Aufbereitung der Daten. Mit grosser Wahrscheinlichkeit wäre es noch einfacher, schöner und auch effizienter möglich gewesen.
Dateinamen auslesen und aufbereiten

Zeile 4: Es werden alle Dateien (Ordner werden ignoriert) rekursiv aus dem Verzeichnis ausgelesen, das in Zeile 1 gesetzt wurde.
Zeile 15-17: Der Dateinamen wird von der Endung befreit und bei dem Zeichensatz ” – ” getrennt. Die Teilstücke werden im Array $NameParts gespeichert und von überflüssigen Leerzeichen befreit.
Zeile 21-28: Der Array $NameParts wird ausgelesen und in die Eigenschaften der Variable $datacombo geschrieben. Mit Invoke-Expression kann ein Befehl in einer Variable ausgeführt werden, somit besteht die Möglichkeit ein Befehl in Laufzeit zusammen zu setzen.

PowerShell
$FilePath = "Pfad zum Auslesen"

$DataCollection = @()
$Files = Get-ChildItem -Path $FilePath -Recurse | where { !$_.PSIsContainer }

ForEach ($File in $Files) {
    $datacombo = "" | Select "Path", "Size", "NewName", "NP1","NP2","NP3","NP4","NP5","Resolution","Extension"
    $NameParts = @()

    $datacombo.Path = $File.Fullname
    $Size = $File.Length
    $datacombo.Size = $Size/1MB
    $datacombo.Extension = $File.Extension

    $Name = $File.Name -Replace($File.Extension,"")
    $NameParts = $Name -Split" - "
    $NameParts = $NameParts | %{$_.Trim()}

    $i = 1

    ForEach ($Part in $NameParts) {

        If ($Part -eq "720p" -or $Part -eq "1080p" -or $Part -eq "HD") {
            $datacombo.Resolution = $Part
        } Else {
            $temp = '$datacombo.NP'+$i+'=$Part'
            Invoke-Expression $temp
        }
        $i++
    }

    $DataCollection += $datacombo

}

$DataCollection | Export-Csv -Path "Pfad für CSV-Datei" -Encoding "Unicode" -NoTypeInformation</pre>
 

<strong>Dateien umbenennen</strong>

Zeile 3: Um allfälligen Codierungsfehlern aus dem Weg zu gehen, wird der Inhalt der Datei ausgelesen und als Unicode in eine temporäre Datei geschrieben.
<pre class="lang:ps decode:true toolbar:1 scroll:true " title="Dateien umbenennen">$FilePath = "Pfad zur CSV-Datei"

Get-Content $FilePath | Out-File .temp.csv -Encoding Unicode
sleep(5)
$Import = Import-Csv -Path .temp.csv -Delimiter ";"
Remove-Item -Path .temp.csv

$Import | ForEach-Object { 
    $File = Get-ItemProperty -Path $_.Path
    If ($_.NewName -ne $File.Name) {
        Rename-Item -Path $_.Path -NewName $_.NewName
    }
}

Create Homefolder

Ein einfaches Script zum Erstellen von Homefoldern mit den entsprechenden Rechten für die Folder Redirection (User als Owner). Anstatt es eigenständig zu nutzen, kann es auch in ein Script zur Benutzererstellung implementiert werden.
Zeile 4: Hier wird die Quelle der Benutzernamen (SamAccountName) angegeben, in diesem Fall ein Import einer CSV-Datei.
Zeile 9-10: Überprüfung ob bereits ein Ordner mit dem Namen vorhanden ist.

PowerShell
$Path = "Pfad zur CSV-Datei"
$HomeFolderRoot = "Share aller Homefolder"

Import-Csv -Path $Path |  %{
    $username = $_.SamAccountName
    $HomeFolder = $HomeFolderRoot + $username
    $NTAccount = "Domain$username"

    $check = Test-Path -Path $HomeFolder -PathType Container
    If ($check -eq $false){
        New-Item $HomeFolder -Type Directory &gt; null
        $acl = Get-Acl $HomeFolder
        $acl.SetOwner([System.Security.Principal.NTAccount] "$NTAccount")
        $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$NTAccount","FullControl","ContainerInherit, ObjectInherit", "None", "Allow")
        $acl.AddAccessRule($rule)
        Set-Acl $HomeFolder $acl
        echo "Homefolder created for User $username"
    } else {
        echo "Homefolder already exists for User $username"
    }
}

Delete Domain Users

Am Arbeitsplatz wurden beim Entfernen von Domänen Benutzern oft nur die AD Accounts gelöscht. Die Mailkonten werden so zwar mitgelöscht, die Benutzerordner (Profil und Home) jedoch nicht. So fielen je länger je mehr Daten an, die zu keinem Benutzer mehr gehörten. Aus diesem Grund entstand das Script, das alle AD Accounts in einer OU löscht und auch die Benutzerordner berücksichtigt.
Da die Ordnerberechtigungen nicht immer ein direktes Löschen zuliessen, setzt das Script vor dem Löschen bei allen Ordnern den Owner auf die Lokale Administratorgruppe und fügt diese mit Full Control den Berechtigungen hinzu. Für das Anpassen der Berechtigungen kommt das Programm SetACL zum Einsatz. Als weiteres kommt ActiveRoles Management Shell for Active Directory von Quest zum Einsatz.

In den Zeilen mit einem Aufruf des Programms SetACL muss jeweils der Pfad und die Benutzergruppe angepasst werden.
Profil und Profil.V2 da wir lange Zeit eine gemischte Umgebung mit Windows XP und Windows 7 hatten.

PowerShell
# Variablen definieren
$UserColl = @()
$acllog = ""
$pslog = ""
$DeletedFolders = "Pfad zum Log für gelöschte Ordner"
$SetACLLog = "Pfad zum Log von SetACL"
$ErrorLog = "Pfad zum Errorlog"
$SearchRoot = "OU mit AD Accounts die gelöscht werden sollen"

# User in OU auslesen
$Users = Get-QADUser -SearchRoot $SearchRoot -SearchScope OneLevel

# Vorgang für jeden User durchführen
ForEach ($User in $Users) {

    $HomeDir = $User.HomeDirectory
    $ProfileDir = $User.ProfilePath
    $ProfileV2 = $User.ProfilePath + ".V2"
    $DistinguishedName = $User.DN
    $Username = $User.SamAccountName

    # Falls ein .V2 Profil vorhanden ist, werden Benutzer und Rechte angepasst und der Ordner gelöscht
    if (Test-Path -Path $ProfileV2) {
        SetACL.exe -on "$ProfileV2" -ot file -actn setowner -ownr "n:LOCALAdministrators" -rec cont_obj -log $SetACLLog -silent
        SetACL.exe -on "$ProfileV2" -ot file -actn ace -ace "n:LOCALAdministrators;p:full" -rec cont_obj -log $SetACLLog -silent

        Try {     
            cmd /c "rmdir /S /Q $ProfileV2"
            $ProfileV2 | Add-Content $DeletedFolders
        } Catch {
            "ERROR beim Entfernen $filename: $_.ExeptionMessage" | Add-Content $ErrorLog
            Write-Output "ProfilV2 von $Username konnte nicht gelöscht werden"
        }
    }

    # Falls ein Profil vorhanden ist, werden Benutzer und Rechte angepasst und der Ordner gelöscht
    if (Test-Path -Path $ProfileDir) {
        SetACL.exe -on "$ProfileDir" -ot file -actn setowner -ownr "n:LOCALAdministrators" -rec cont_obj -log $SetACLLog -silent 
	SetACL.exe -on "$ProfileDir" -ot file -actn ace -ace "n:LOCALAdministrators;p:full" -rec cont_obj -log $SetACLLog -silent

        Try {     
            cmd /c "rmdir /S /Q $ProfileDir"
            $ProfileDir | Add-Content $DeletedFolders
        } Catch {
            "ERROR beim Entfernen $filename: $_.Exception.Message" | Add-Content $ErrorLog
            Write-Output "Profil von $Username konnte nicht gelöscht werden"
        }
    }

    # Falls ein Home Ordner vorhanden ist, werden Benutzer und Rechte angepasst und er Ordner gelöscht
    if (Test-Path -Path $HomeDir) {
        SetACL.exe -on "$HomeDir" -ot file -actn setowner -ownr "n:LOCALAdministrators" -rec cont_obj -log $SetACLLog -silent
        SetACL.exe -on "$HomeDir" -ot file -actn ace -ace "n:LOCALAdministrators;p:full" -rec cont_obj -log $SetACLLog -silent

        Try {     
            cmd /c "rmdir /S /Q $HomeDir"
            $HomeDir | Add-Content $DeletedFolders
        } Catch {
            "ERROR beim Entfernen $filename: $_.Exception.Message" | Add-Content $ErrorLog
            Write-Output "Home von $Username konnte nicht gelöscht werden"
        }  
    }

    Try {
        # Löschen des AD Benutzerobjekts
        Remove-QADObject -Identity $DistinguishedName -Force -DeleteTree 
    } Catch {
        "ERROR beim Entfernen: $_.Exception.Message" | Add-Content $ErrorLog
        Write-Output "Benutzerkonto von $Username konnte nicht gelöscht werden"
    }   
}

Anfänge Informatik

Das Hobby, das ich zum Beruf machte. Bestimmt nicht das erste und älteste Hobby von mir, jedoch das, welches mich am meisten geprägt hat.
Computer faszinierten mich schon von klein auf. Lange Zeit hauptsächlich Hardware und Gaming, inzwischen hat sich der Bereich Gaming etwas in den Hintergrund gestellt und hat dem Bereich Systemtechnik mehr Raum gegeben. Vor allem das vereinfachen oder automatisieren von sicher wiederholenden Abläufen setze ich zu Hause sowie am Arbeitsplatz gerne um.
Da ich am Arbeitsplatz vorrangig Windows Servern (2003 bis 2012R2) administriere, benutze ich meistens die Scriptsprache Powershell. Aus diesem Grund werde ich hier in erster Linie solche Scripts bzw. Ausschnitte daraus vorstellen.