diff --git a/Network Share Mounter/helper/ActivityController.swift b/Network Share Mounter/helper/ActivityController.swift
index 6410a3bc0de556d0615130a74ae6df84200ff93e..1d256efe45bb6f6ea8cf52d99b62ede8c6e1bfc0 100644
--- a/Network Share Mounter/helper/ActivityController.swift	
+++ b/Network Share Mounter/helper/ActivityController.swift	
@@ -10,129 +10,278 @@ import Foundation
 import AppKit
 import OSLog
 
-
+/// Monitors system events and responds with appropriate actions for network shares
 ///
-/// class to handle system (NSWorkspace) notifications when system starts sleeping
+/// The ActivityController registers for system events such as sleep,
+/// logout, wake up, and login. Based on these events, network shares
+/// are either mounted or unmounted as appropriate.
 class ActivityController {
     
-    var prefs = PreferenceManager()
-    var appDelegate: AppDelegate
-
+    // MARK: - Properties
+    
+    /// Access to user preferences
+    private let prefs = PreferenceManager()
+    
+    /// Reference to AppDelegate for accessing important app components
+    private weak var appDelegate: AppDelegate?
+    
+    // MARK: - Initialization
+    
+    /// Initializes the controller and starts monitoring system events
+    /// 
+    /// - Parameter appDelegate: Reference to the AppDelegate instance
     init(appDelegate: AppDelegate) {
         self.appDelegate = appDelegate
         startMonitoring()
     }
-       
-    /// initialize observers to get notifications
+    
+    // MARK: - Observer Management
+    
+    /// Registers the controller for all relevant system notifications
+    ///
+    /// This method registers observers for the following categories:
+    /// - System events (sleep, wake, shutdown)
+    /// - Session events (active, inactive)
+    /// - Timer events for regular actions
+    /// - Custom app events (mount, unmount)
+    /// - Network changes
     func startMonitoring() {
-        // create an observer for NSWorkspace notifications
-        // first stop possible exitisting observers
+        // Remove existing observers to avoid duplicate registrations
         NSWorkspace.shared.notificationCenter.removeObserver(self)
         DistributedNotificationCenter.default.removeObserver(self)
         
-        // trigger if macOS sleep will be started
-        NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(unmountShares), name: NSWorkspace.willSleepNotification, object: nil)
-        // trigger if session becomes inactive
-        NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(unmountShares), name: NSWorkspace.sessionDidResignActiveNotification, object: nil)
-        // trigger if user logs out or shuts down macOS
-        NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(unmountShares), name: NSWorkspace.willPowerOffNotification, object: nil)
-        // trigger if Mac wakes up from sleep
-        NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(wakeupFromSleep), name: NSWorkspace.didWakeNotification, object: nil)
-        // trigger if user session becomes active
-        NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(mountShares), name: NSWorkspace.sessionDidBecomeActiveNotification, object: nil)
-        // time trigger to reauthenticate
-        NotificationCenter.default.addObserver(self, selector: #selector(processAutomaticSignIn), name: Defaults.nsmAuthTriggerNotification, object: nil)
-        // time trigger to mount shares/check for new profile
-        NotificationCenter.default.addObserver(self, selector: #selector(timeGoesBySoSlowly), name: Defaults.nsmTimeTriggerNotification, object: nil)
-        // trigger to mount shares
-        NotificationCenter.default.addObserver(self, selector: #selector(mountShares), name: Defaults.nsmMountTriggerNotification, object: nil)
-        // triogger to unmount shares
-        NotificationCenter.default.addObserver(self, selector: #selector(unmountShares), name: Defaults.nsmUnmountTriggerNotification, object: nil)
-        // trigger to manually mount shares
-        NotificationCenter.default.addObserver(self, selector: #selector(mountSharesWithUserTrigger), name: Defaults.nsmMountManuallyTriggerNotification, object: nil)
-        // trigger on network change to mount shares
-        NotificationCenter.default.addObserver(self, selector: #selector(mountSharesWithUserTrigger), name: Defaults.nsmNetworkChangeTriggerNotification, object: nil)
-        // triger reconstruct menu
-        NotificationCenter.default.addObserver(self, selector: #selector(reconstructMenuTrigger), name: Defaults.nsmReconstructMenuTriggerNotification, object: nil)
-        
-        // get notification for "CCAPICCacheChangedNotification" (as defined in kcm.h) changes
-        DistributedNotificationCenter.default.addObserver(self, selector: #selector(processAutomaticSignIn), name: "CCAPICCacheChangedNotification" as CFString as NSNotification.Name, object: nil)
+        Logger.activityController.debug("Starting monitoring of system events")
+        
+        // System event observers
+        NSWorkspace.shared.notificationCenter.addObserver(
+            self,
+            selector: #selector(unmountShares),
+            name: NSWorkspace.willSleepNotification,
+            object: nil
+        )
+        
+        NSWorkspace.shared.notificationCenter.addObserver(
+            self,
+            selector: #selector(unmountShares),
+            name: NSWorkspace.sessionDidResignActiveNotification,
+            object: nil
+        )
+        
+        NSWorkspace.shared.notificationCenter.addObserver(
+            self,
+            selector: #selector(unmountShares),
+            name: NSWorkspace.willPowerOffNotification,
+            object: nil
+        )
+        
+        NSWorkspace.shared.notificationCenter.addObserver(
+            self,
+            selector: #selector(wakeupFromSleep),
+            name: NSWorkspace.didWakeNotification,
+            object: nil
+        )
+        
+        NSWorkspace.shared.notificationCenter.addObserver(
+            self,
+            selector: #selector(mountShares),
+            name: NSWorkspace.sessionDidBecomeActiveNotification,
+            object: nil
+        )
+        
+        // App-specific observers
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(processAutomaticSignIn),
+            name: Defaults.nsmAuthTriggerNotification,
+            object: nil
+        )
+        
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(timeGoesBySoSlowly),
+            name: Defaults.nsmTimeTriggerNotification,
+            object: nil
+        )
+        
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(mountShares),
+            name: Defaults.nsmMountTriggerNotification,
+            object: nil
+        )
+        
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(unmountShares),
+            name: Defaults.nsmUnmountTriggerNotification,
+            object: nil
+        )
+        
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(mountSharesWithUserTrigger),
+            name: Defaults.nsmMountManuallyTriggerNotification,
+            object: nil
+        )
+        
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(mountSharesWithUserTrigger),
+            name: Defaults.nsmNetworkChangeTriggerNotification,
+            object: nil
+        )
+        
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(reconstructMenuTrigger),
+            name: Defaults.nsmReconstructMenuTriggerNotification,
+            object: nil
+        )
+        
+        // Kerberos cache changes
+        DistributedNotificationCenter.default.addObserver(
+            self,
+            selector: #selector(processAutomaticSignIn),
+            name: "CCAPICCacheChangedNotification" as CFString as NSNotification.Name,
+            object: nil
+        )
+        
+        Logger.activityController.debug("All observers successfully registered")
     }
     
-    // call unmount shares on NSWorkspace notification
+    // MARK: - System Event Handlers
+    
+    /// Unmounts all network shares
+    ///
+    /// Called when:
+    /// - System enters sleep mode
+    /// - Session becomes inactive
+    /// - System shuts down
+    /// - User manually triggers unmount
     @objc func unmountShares() {
-        if let mounter = appDelegate.mounter {
-            Logger.activityController.debug(" ▶︎ unmountAllShares called by willSleepNotification.")
-            Task {
-                await mounter.unmountAllMountedShares()
-            }
+        guard let mounter = appDelegate?.mounter else {
+            Logger.activityController.error("Unmount failed: Mounter not available")
+            return
+        }
+        
+        let notificationName = (Thread.callStackSymbols.first ?? "Unknown")
+            .components(separatedBy: " ")
+            .last ?? "Unknown"
+        
+        Logger.activityController.debug("▶︎ unmountAllShares called by \(notificationName)")
+        
+        Task {
+            await mounter.unmountAllMountedShares()
+            Logger.activityController.debug("All shares successfully unmounted")
         }
     }
     
-    // functions called after wake up
+    /// Handles system wake up from sleep
+    ///
+    /// Mounts all configured shares and restarts Finder
+    /// to work around known macOS issues
     @objc func wakeupFromSleep() {
-        if let mounter = appDelegate.mounter {
-            Logger.activityController.debug(" ▶︎ mountGivenShares called by didWakeNotification.")
-            Task {
-                // await self.mounter.mountAllShares(userTriggered: true)
-                await mounter.mountGivenShares()
-                Logger.activityController.debug(" 🐛 Restart Finder to bypass a presumed bug in macOS.")
-                let finderController = FinderController()
-                await finderController.restartFinder()
-            }
+        guard let mounter = appDelegate?.mounter else {
+            Logger.activityController.error("Wake-up processing failed: Mounter not available")
+            return
+        }
+        
+        Logger.activityController.debug("▶︎ mountGivenShares called by didWakeNotification")
+        
+        Task {
+            await mounter.mountGivenShares()
+            Logger.activityController.debug("🐛 Restarting Finder to bypass a presumed bug in macOS")
+            
+            let finderController = FinderController()
+            await finderController.restartFinder()
         }
     }
     
-    // call mount shares on NSWorkspace notification
+    /// Mounts configured network shares
+    ///
+    /// Called when:
+    /// - Session becomes active
+    /// - App mount requests
     @objc func mountShares() {
-        if let mounter = appDelegate.mounter {
-            Logger.activityController.debug(" ▶︎ mountGivenShares called by didWakeNotification.")
-            Task {
-                // await self.mounter.mountAllShares(userTriggered: true)
-                await mounter.mountGivenShares()
-            }
+        guard let mounter = appDelegate?.mounter else {
+            Logger.activityController.error("Mount failed: Mounter not available")
+            return
+        }
+        
+        let notificationName = (Thread.callStackSymbols.first ?? "Unknown")
+            .components(separatedBy: " ")
+            .last ?? "Unknown"
+        
+        Logger.activityController.debug("▶︎ mountGivenShares called by \(notificationName)")
+        
+        Task {
+            await mounter.mountGivenShares()
+            Logger.activityController.debug("All shares successfully mounted")
         }
     }
     
-    // call automatic sign in on notification
+    // MARK: - Authentication Handlers
+    
+    /// Starts the automatic sign-in process for Kerberos
+    ///
+    /// Only executes when Kerberos authentication is configured.
     @objc func processAutomaticSignIn() {
-        // run authenticaction only if kerberos auth is enabled
-        // forcing unwrapping the optional is OK, since values are "registered"
-        // and set to empty string if not set
-        // check if a kerberos domain/realm is set and is not empty
-        if let krbRealm = self.prefs.string(for: .kerberosRealm), !krbRealm.isEmpty {
-            Task {
-                Logger.activityController.debug(" ▶︎ kerberos realm configured, processing AutomaticSignIn.")
-                await appDelegate.automaticSignIn.signInAllAccounts()
-            }
+        // Check if a Kerberos realm is configured
+        guard let krbRealm = self.prefs.string(for: .kerberosRealm), !krbRealm.isEmpty else {
+            Logger.activityController.debug("No Kerberos realm configured, skipping AutomaticSignIn")
+            return
+        }
+        
+        Task {
+            Logger.activityController.debug("▶︎ Kerberos realm configured, processing AutomaticSignIn")
+            await appDelegate?.automaticSignIn.signInAllAccounts()
+            Logger.activityController.info("Automatic sign-in completed successfully")
         }
     }
     
-    // call mount shares with manually parameter and, if configured, renew kerberos tickets
+    /// Mounts shares after user request
+    ///
+    /// First performs Kerberos authentication, then mounts the shares
     @objc func mountSharesWithUserTrigger() {
-        // renew tickets
+        // Renew Kerberos tickets
         processAutomaticSignIn()
-        // mount shares
-        if let mounter = appDelegate.mounter {
-            Logger.activityController.debug(" ▶︎ mountGivenShares with user-trigger called.")
-            Task {
-                await mounter.mountGivenShares(userTriggered: true)
-            }
+        
+        guard let mounter = appDelegate?.mounter else {
+            Logger.activityController.error("User request for mounting failed: Mounter not available")
+            return
+        }
+        
+        Logger.activityController.debug("▶︎ mountGivenShares with user-trigger called")
+        
+        Task {
+            await mounter.mountGivenShares(userTriggered: true)
+            Logger.activityController.info("Shares successfully mounted after user request")
         }
     }
     
+    /// Updates the app menu
+    ///
+    /// Rebuilds the app menu based on current status
     @objc func reconstructMenuTrigger() {
-        if let mounter = appDelegate.mounter {
-            Logger.activityController.debug(" ▶︎ reconstruct menu trigger called.")
-            Task { @MainActor in
-                await appDelegate.constructMenu(withMounter: mounter)
-            }
+        guard let mounter = appDelegate?.mounter else {
+            Logger.activityController.error("Menu update failed: Mounter not available")
+            return
+        }
+        
+        Logger.activityController.debug("▶︎ Menu reconstruction called")
+        
+        Task { @MainActor in
+            await appDelegate?.constructMenu(withMounter: mounter)
+            Logger.activityController.debug("Menu successfully updated")
         }
     }
     
-    /// perform some actions now and then, such as renew Kerberos tickets,
-    /// mount shares etc.
+    /// Performs periodic tasks
     ///
+    /// This method is called by a timer and checks:
+    /// - Changes in MDM profile
+    /// - Status of mounted shares
+    /// 
     /// Time goes by so slowly
     /// Time goes by so slowly
     /// Time goes by so slowly for those who wait
@@ -140,15 +289,36 @@ class ActivityController {
     /// Those who run seem to have all the fun
     /// I'm caught up, I don't know what to do
     @objc func timeGoesBySoSlowly() {
-        if let mounter = appDelegate.mounter {
-            Logger.activityController.debug("⏰ Time goes by so slowly: got timer notification.")
-            Logger.activityController.debug(" ▶︎ ...check for possible MDM profile changes.")
-            // call updateShareArray() to reflect possible changes in MDM profile?
-            Task {
-                await mounter.shareManager.updateShareArray()
-                Logger.activityController.debug(" ▶︎ ...finally call mountGivenShares.")
-                await mounter.mountGivenShares()
-            }
+        guard let mounter = appDelegate?.mounter else {
+            Logger.activityController.error("Timer processing failed: Mounter not available")
+            return
+        }
+        
+        Logger.activityController.debug("⏰ Time goes by so slowly: Timer notification received")
+        Logger.activityController.debug("▶︎ ...checking for possible MDM profile changes")
+        
+        // Check ShareArray for possible changes in MDM profile
+        Task {
+            await mounter.shareManager.updateShareArray()
+            Logger.activityController.debug("▶︎ ...calling mountGivenShares")
+            await mounter.mountGivenShares()
+            Logger.activityController.debug("Timer processing completed successfully")
+        }
+    }
+    
+    // MARK: - Helpers for utilizing the cliTaskAsync method
+    
+    /// Executes a CLI command asynchronously with error handling
+    /// 
+    /// - Parameter command: The command to execute
+    /// - Returns: The command output if successful
+    /// - Throws: Any errors that occur during command execution
+    private func executeCommand(_ command: String) async throws -> String {
+        do {
+            return try await cliTaskAsync(command)
+        } catch {
+            Logger.activityController.error("Command execution failed: \(command), error: \(error.localizedDescription)")
+            throw error
         }
     }
 }
diff --git a/Network Share Mounter/helper/AutomaticSignIn.swift b/Network Share Mounter/helper/AutomaticSignIn.swift
index f3c0fd27e5d437964c011a32950206553ecdf749..0b393ef94947362a00b1680323f44cf75df2561a 100644
--- a/Network Share Mounter/helper/AutomaticSignIn.swift	
+++ b/Network Share Mounter/helper/AutomaticSignIn.swift	
@@ -11,139 +11,298 @@ import Foundation
 import OSLog
 import dogeADAuth
 
+/// Mögliche Fehler bei der automatischen Anmeldung
+public enum AutoSignInError: Error, LocalizedError {
+    case noSRVRecords(String)
+    case noActiveTickets
+    case keychainAccessFailed(Error)
+    case authenticationFailed(String)
+    case networkError(String)
+    
+    public var errorDescription: String? {
+        switch self {
+        case .noSRVRecords(let domain):
+            return "Keine SRV-Einträge gefunden für Domäne: \(domain)"
+        case .noActiveTickets:
+            return "Keine aktiven Kerberos-Tickets vorhanden"
+        case .keychainAccessFailed(let error):
+            return "Zugriff auf Keychain fehlgeschlagen: \(error.localizedDescription)"
+        case .authenticationFailed(let message):
+            return "Authentifizierung fehlgeschlagen: \(message)"
+        case .networkError(let message):
+            return "Netzwerkfehler: \(message)"
+        }
+    }
+}
+
+/// Benutzer-Sitzungsobjekt mit Informationen zur Authentifizierung
 public struct Doge_SessionUserObject {
+    /// Benutzerprincipal (z.B. user@DOMAIN.COM)
     var userPrincipal: String
+    /// Active Directory Sitzung
     var session: dogeADSession
+    /// Gibt an, ob Passwort-Aging aktiviert ist
     var aging: Bool
+    /// Ablaufdatum des Passworts, falls vorhanden
     var expiration: Date?
+    /// Verbleibende Tage bis zum Ablauf des Passworts
     var daysToGo: Int?
+    /// Benutzerinformationen aus Active Directory
     var userInfo: ADUserRecord?
 }
 
+/// Actor für die automatische Anmeldung an Active Directory
+/// 
+/// Verwaltet automatische Anmeldungen für mehrere Konten
 actor AutomaticSignIn {
+    /// Gemeinsame Instanz (Singleton)
     static let shared = AutomaticSignIn()
     
+    /// Preference Manager für Einstellungen
     var prefs = PreferenceManager()
     
+    /// Accounts Manager für Benutzerkontenverwaltung
     let accountsManager = AccountsManager.shared
     
+    /// Private Initialisierung für Singleton-Pattern
     private init() {}
     
+    /// Meldet alle relevanten Konten automatisch an
+    /// 
+    /// Basierend auf Einstellungen werden entweder alle Konten oder nur das Standard-Konto angemeldet.
     func signInAllAccounts() async {
+        Logger.automaticSignIn.info("Starte automatischen Anmeldeprozess")
+        
         let klist = KlistUtil()
-        _ = await klist.klist().map({ $0.principal })
+        // Alle verfügbaren Kerberos-Principals abrufen
+        let principals = await klist.klist().map({ $0.principal })
         let defaultPrinc = await klist.defaultPrincipal
         
-        // sign in only for defaultPrinc-Account if singleUserMode == true or only one account exists, walk through all accounts
-        // if singleUserMode == false and more than 1 account exists
+        Logger.automaticSignIn.debug("Gefundene Principals: \(principals.joined(separator: ", "))")
+        Logger.automaticSignIn.debug("Standard-Principal: \(defaultPrinc ?? "Keiner")")
+        
+        // Konten abrufen und Anmeldestrategie bestimmen:
+        // - Wenn Single-User-Modus aktiv ist, nur Standard-Konto anmelden
+        // - Ansonsten alle Konten anmelden
         let accounts = await accountsManager.accounts
         let accountsCount = accounts.count
+        
         for account in accounts {
             if !prefs.bool(for: .singleUserMode) || account.upn == defaultPrinc || accountsCount == 1 {
+                Logger.automaticSignIn.info("Automatische Anmeldung für Konto: \(account.upn)")
                 let worker = AutomaticSignInWorker(account: account)
                 await worker.checkUser()
             }
         }
+        
+        // Standard-Principal wiederherstellen
         if let defPrinc = defaultPrinc {
-            _ = try? await cliTask("kswitch -p \(defPrinc)")
+            do {
+                let output = try await cliTaskAsync("kswitch -p \(defPrinc)")
+                Logger.automaticSignIn.debug("kswitch Ausgabe: \(output)")
+            } catch {
+                Logger.automaticSignIn.error("Fehler beim Umschalten auf Standard-Principal: \(error.localizedDescription)")
+            }
         }
     }
 }
 
+/// Worker-Actor für die Anmeldung eines einzelnen Kontos
+/// 
+/// Implementiert die Delegate-Methoden für dogeADUserSessionDelegate
 actor AutomaticSignInWorker: dogeADUserSessionDelegate {
     
+    /// Preference Manager für Einstellungen
     var prefs = PreferenceManager()
+    
+    /// Das zu verwaltende Benutzerkonto
     var account: DogeAccount
+    
+    /// Active Directory Sitzung
     var session: dogeADSession
+    
+    /// DNS-Resolver für SRV-Einträge
     var resolver = SRVResolver()
+    
+    /// Die Domäne des Benutzerkontos
     let domain: String
     
+    /// Initialisiert einen neuen Worker mit einem Benutzerkonto
+    /// 
+    /// - Parameter account: Das Benutzerkonto für die Anmeldung
     init(account: DogeAccount) {
         self.account = account
         domain = account.upn.userDomain() ?? ""
         self.session = dogeADSession(domain: domain, user: account.upn.user())
         self.session.setupSessionFromPrefs(prefs: prefs)
+        
+        Logger.automaticSignIn.debug("Worker initialisiert für Benutzer: \(account.upn), Domäne: \(self.domain)")
     }
     
+    /// Überprüft den Benutzer und führt die Anmeldung durch
+    /// 
+    /// Der Prozess umfasst:
+    /// 1. Auflösen der SRV-Einträge für LDAP-Server
+    /// 2. Überprüfung bestehender Kerberos-Tickets
+    /// 3. Abrufen von Benutzerinformationen oder Authentifizierung
     func checkUser() async {
         let klist = KlistUtil()
         let princs = await klist.klist().map({ $0.principal })
         
-        await withCheckedContinuation { continuation in
-            resolver.resolve(query: "_ldap._tcp." + domain.lowercased()) { result in
-                Logger.automaticSignIn.info("SRV Response for: _ldap._tcp.\(self.domain, privacy: .public)")
+        // SRV-Einträge für LDAP auflösen
+        do {
+            let records = try await resolveSRVRecords()
+            
+            // Wenn SRV-Einträge gefunden wurden und das Konto ein gültiges Ticket hat
+            if !records.SRVRecords.isEmpty {
+                if princs.contains(where: { $0.lowercased() == self.account.upn }) {
+                    Logger.automaticSignIn.info("Gültiges Ticket gefunden für: \(self.account.upn)")
+                    await getUserInfo()
+                } else {
+                    Logger.automaticSignIn.info("Kein gültiges Ticket gefunden, starte Authentifizierung")
+                    await auth()
+                }
+            } else {
+                Logger.automaticSignIn.warning("Keine SRV-Einträge gefunden für Domäne: \(self.domain)")
+                throw AutoSignInError.noSRVRecords(domain)
+            }
+        } catch {
+            Logger.automaticSignIn.error("Fehler beim Auflösen der SRV-Einträge: \(error.localizedDescription)")
+            // Bei Fehlern trotzdem Authentifizierung versuchen
+            await auth()
+        }
+    }
+    
+    /// Löst SRV-Einträge für die LDAP-Dienste auf
+    /// 
+    /// - Returns: Die gefundenen SRV-Einträge
+    /// - Throws: Fehler, wenn keine Einträge gefunden werden
+    private func resolveSRVRecords() async throws -> SRVResult {
+        return try await withCheckedThrowingContinuation { continuation in
+            let query = "_ldap._tcp." + domain.lowercased()
+            Logger.automaticSignIn.debug("Löse SRV-Einträge auf für: \(query)")
+            
+            resolver.resolve(query: query) { result in
+                Logger.automaticSignIn.info("SRV-Antwort für: \(query)")
                 switch result {
                 case .success(let records):
-                    if !records.SRVRecords.isEmpty {
-                        if princs.contains(where: { $0.lowercased() == self.account.upn }) {
-                            Task {
-                                await self.getUserInfo()
-                            }
-                        }
-                    } else {
-                        Logger.automaticSignIn.info("No SRV records found.")
-                    }
+                    continuation.resume(returning: records)
                 case .failure(let error):
-                    Logger.automaticSignIn.error("No DNS results for domain \(self.domain, privacy: .public), unable to automatically login. Error: \(error, privacy: .public)")
+                    Logger.automaticSignIn.error("Keine DNS-Ergebnisse für Domäne \(self.domain), automatische Anmeldung nicht möglich. Fehler: \(error)")
+                    continuation.resume(throwing: error)
                 }
-                continuation.resume()
             }
         }
-        
-        await auth()
     }
     
+    /// Authentifiziert den Benutzer mit Keychain-Zugangsdaten
+    /// 
+    /// Ruft das Passwort aus dem Keychain ab und startet den Authentifizierungsprozess
     func auth() async {
         let keyUtil = KeychainManager()
+        
         do {
+            // Passwort aus Keychain abrufen
             if let pass = try keyUtil.retrievePassword(forUsername: account.upn.lowercaseDomain(), andService: Defaults.keyChainService) {
+                Logger.automaticSignIn.debug("Passwort für \(self.account.upn) aus Keychain abgerufen")
                 account.hasKeychainEntry = true
                 session.userPass = pass
                 session.delegate = self
+                
+                // Authentifizierung starten
                 await session.authenticate()
+            } else {
+                Logger.automaticSignIn.warning("Kein Passwort im Keychain gefunden für: \(self.account.upn)")
+                account.hasKeychainEntry = false
+                NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["KrbAuthError": MounterError.authenticationError])
             }
         } catch {
+            Logger.automaticSignIn.error("Fehler beim Zugriff auf Keychain: \(error.localizedDescription)")
             account.hasKeychainEntry = false
             NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["KrbAuthError": MounterError.authenticationError])
         }
     }
     
+    /// Ruft Benutzerinformationen vom Active Directory ab
+    /// 
+    /// Wechselt zum Benutzer-Principal und ruft Detailinformationen ab
     func getUserInfo() async {
-        _ = try? await cliTask("kswitch -p \(session.userPrincipal)")
-        session.delegate = self
-        await session.userInfo()
+        do {
+            // Zum Benutzer-Principal wechseln
+            let output = try await cliTaskAsync("kswitch -p \(session.userPrincipal)")
+            Logger.automaticSignIn.debug("kswitch Ausgabe: \(output)")
+            
+            // Benutzerdaten abrufen
+            session.delegate = self
+            await session.userInfo()
+        } catch {
+            Logger.automaticSignIn.error("Fehler beim Abrufen der Benutzerinformationen: \(error.localizedDescription)")
+        }
     }
     
+    // MARK: - dogeADUserSessionDelegate Methoden
+    
+    /// Wird aufgerufen, wenn die Authentifizierung erfolgreich war
     func dogeADAuthenticationSucceded() async {
-        Logger.automaticSignIn.info("Auth succeeded for user: \(self.account.upn, privacy: .public)")
-        _ = try? await cliTask("kswitch -p \(session.userPrincipal)")
-        NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["krbAuthenticated": MounterError.krbAuthSuccessful])
-        await session.userInfo()
+        Logger.automaticSignIn.info("Authentifizierung erfolgreich für: \(self.account.upn)")
+        
+        do {
+            // Zum authentifizierten Benutzer wechseln
+            let output = try await cliTaskAsync("kswitch -p \(session.userPrincipal)")
+            Logger.automaticSignIn.debug("kswitch Ausgabe: \(output)")
+            
+            // Erfolg mitteilen
+            NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["krbAuthenticated": MounterError.krbAuthSuccessful])
+            
+            // Benutzerinformationen abrufen
+            await session.userInfo()
+        } catch {
+            Logger.automaticSignIn.error("Fehler nach erfolgreicher Authentifizierung: \(error.localizedDescription)")
+        }
     }
     
+    /// Wird aufgerufen, wenn die Authentifizierung fehlgeschlagen ist
+    /// 
+    /// - Parameters:
+    ///   - error: Fehlertyp
+    ///   - description: Fehlerbeschreibung
     func dogeADAuthenticationFailed(error: dogeADSessionError, description: String) {
-        Logger.automaticSignIn.info("Auth failed for user: \(self.account.upn, privacy: .public), Error: \(description, privacy: .public)")
+        Logger.automaticSignIn.info("Authentifizierung fehlgeschlagen für: \(self.account.upn), Fehler: \(description)")
+        
         switch error {
         case .AuthenticationFailure, .PasswordExpired:
+            // Bei Authentifizierungsfehlern oder abgelaufenen Passwörtern:
+            // - Benachrichtigung senden
+            // - Falsches Passwort aus Keychain entfernen
             NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["KrbAuthError": MounterError.krbAuthenticationError])
-            Logger.automaticSignIn.info("Removing bad password from keychain")
+            Logger.automaticSignIn.info("Entferne ungültiges Passwort aus Keychain")
+            
             let keyUtil = KeychainManager()
             do {
                 try keyUtil.removeCredential(forUsername: account.upn)
-                Logger.automaticSignIn.info("Successfully removed keychain item")
+                Logger.automaticSignIn.info("Keychain-Eintrag erfolgreich entfernt")
             } catch {
-                Logger.automaticSignIn.info("Failed to remove keychain item for username \(self.account.upn)")
+                Logger.automaticSignIn.error("Fehler beim Entfernen des Keychain-Eintrags für: \(self.account.upn), Fehler: \(error.localizedDescription)")
             }
+            
         case .OffDomain:
-            Logger.automaticSignIn.info("Outside Kerberos realm network")
+            // Wenn außerhalb der Kerberos-Domäne
+            Logger.automaticSignIn.info("Außerhalb des Kerberos-Realm-Netzwerks")
             NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["krbOffDomain": MounterError.offDomain])
+            
         default:
+            Logger.automaticSignIn.warning("Unbehandelter Authentifizierungsfehler: \(error)")
             break
         }
     }
     
+    /// Wird aufgerufen, wenn Benutzerinformationen erfolgreich abgerufen wurden
+    /// 
+    /// - Parameter user: Abgerufene Benutzerinformationen
     func dogeADUserInformation(user: ADUserRecord) {
-        Logger.automaticSignIn.debug("User info: \(user.userPrincipal)")
+        Logger.automaticSignIn.debug("Benutzerinformationen erhalten für: \(user.userPrincipal)")
+        
+        // Benutzerinformationen im PreferenceManager speichern
         prefs.setADUserInfo(user: user)
     }
 }
diff --git a/Network Share Mounter/helper/Logger.swift b/Network Share Mounter/helper/Logger.swift
index 53feeb397905c4a264b6ebb4bfe53713789cfd5a..f6d0b5270ff252008accf5e7c7d659ed0c1b8452 100644
--- a/Network Share Mounter/helper/Logger.swift	
+++ b/Network Share Mounter/helper/Logger.swift	
@@ -28,4 +28,5 @@ extension Logger {
     static let directoryOperations = Logger(subsystem: subsystem, category: "directoryOperations")
     static let authUI = Logger(subsystem: subsystem, category: "authUI")
     static let FAU = Logger(subsystem: subsystem, category: "FAU")
+    static let preferences = Logger(subsystem: subsystem, category: "preferences")
 }
diff --git a/Network Share Mounter/helper/NSTaskWrapper.swift b/Network Share Mounter/helper/NSTaskWrapper.swift
index 16e7dc5cc8cf4ef28941718b1e9abe14d5ab0d4f..93a318e86dc12c83c98a3ab643d47c10d2798fd9 100644
--- a/Network Share Mounter/helper/NSTaskWrapper.swift	
+++ b/Network Share Mounter/helper/NSTaskWrapper.swift	
@@ -12,181 +12,357 @@ import SystemConfiguration
 import IOKit
 import OSLog
 
-@discardableResult public func cliTask( _ command: String, arguments: [String]? = nil) -> String {
-
-
-    var commandLaunchPath: String
-    var commandPieces: [String]
-
-    if ( arguments == nil ) {
-        // turn the command into an array and get the first element as the launch path
-        commandPieces = command.components(separatedBy: " ")
-        // loop through the components and see if any end in \
-        if command.contains("\\") {
-
-            // we need to rebuild the string with the right components
-            var x = 0
-
-            for line in commandPieces {
-                if line.last == "\\" {
-                    commandPieces[x] = commandPieces[x].replacingOccurrences(of: "\\", with: " ") + commandPieces.remove(at: x+1)
-                    x -= 1
-                }
-                x += 1
-            }
+/// Definiert mögliche Fehler bei der Ausführung von Shell-Befehlen
+public enum ShellCommandError: Error, LocalizedError {
+    case commandNotFound(String)
+    case executionFailed(String, Int32)
+    case invalidCommand
+    case outputEncodingFailed
+    
+    public var errorDescription: String? {
+        switch self {
+        case .commandNotFound(let command):
+            return "Befehl nicht gefunden: \(command)"
+        case .executionFailed(let command, let code):
+            return "Befehlsausführung fehlgeschlagen: \(command), Exit-Code: \(code)"
+        case .invalidCommand:
+            return "Ungültiger Befehl"
+        case .outputEncodingFailed:
+            return "Ausgabetext konnte nicht kodiert werden"
         }
-        commandLaunchPath = commandPieces.remove(at: 0)
-    } else {
-        commandLaunchPath = command
-        commandPieces = arguments!
-        //myLogger.logit(.debug, message: commandLaunchPath + " " + arguments!.joinWithSeparator(" "))
-    }
-
-    // make sure the launch path is the full path -- think we're going down a rabbit hole here
-
-    if !commandLaunchPath.contains("/") {
-        let realPath = which(commandLaunchPath)
-        commandLaunchPath = realPath
     }
-
-    // set up the NSTask instance and an NSPipe for the result
-
-    let myTask = Process()
-    let myPipe = Pipe()
-    let myErrorPipe = Pipe()
-
-    // Setup and Launch!
-
-    myTask.launchPath = commandLaunchPath
-    myTask.arguments = commandPieces
-    myTask.standardOutput = myPipe
-    // myTask.standardInput = myInputPipe
-    myTask.standardError = myErrorPipe
-
-    myTask.launch()
-    myTask.waitUntilExit()
-
-    let data = myPipe.fileHandleForReading.readDataToEndOfFile()
-    let error = myErrorPipe.fileHandleForReading.readDataToEndOfFile()
-    let outputError = NSString(data: error, encoding: String.Encoding.utf8.rawValue)! as String
-    let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
-
-    return output + outputError
 }
 
-public func cliTaskNoTerm( _ command: String) -> String {
-
-    // This is here because klist -v won't actually trigger the NSTask termination
-
-    // turn the command into an array and get the first element as the launch path
-
-    var commandPieces = command.components(separatedBy: " ")
-
-    // loop through the components and see if any end in \
-
-    if command.contains("\\") {
+/// Cache für Systemwerte, die sich nicht ändern
+private struct SystemInfoCache {
+    static var serialNumber: String?
+    static var macAddress: String?
+}
 
-        // we need to rebuild the string with the right components
-        var x = 0
+/// Führt einen Shell-Befehl aus und gibt die Ausgabe zurück
+///
+/// - Parameters:
+///   - command: Der auszuführende Befehl oder Pfad zur ausführbaren Datei
+///   - arguments: Optionale Befehlsargumente, wenn nicht im command enthalten
+/// - Returns: Die Ausgabe des Befehls (stdout + stderr)
+@discardableResult
+public func cliTask(_ command: String, arguments: [String]? = nil) -> String {
+    Logger.tasks.debug("Ausführung: \(command) \(arguments?.joined(separator: " ") ?? "")")
+    
+    // Sicher die Befehlskomponenten extrahieren
+    let (commandLaunchPath, commandPieces) = prepareCommand(command, arguments: arguments)
+    
+    // Shell-Befehl ausführen
+    let output = executeTask(launchPath: commandLaunchPath, arguments: commandPieces)
+    return output
+}
 
-        for line in commandPieces {
-            if line.last == "\\" {
-                commandPieces[x] = commandPieces[x].replacingOccurrences(of: "\\", with: " ") + commandPieces.remove(at: x+1)
-                x -= 1
+/// Asynchrone Version von cliTask
+///
+/// - Parameters:
+///   - command: Der auszuführende Befehl oder Pfad zur ausführbaren Datei
+///   - arguments: Optionale Befehlsargumente, wenn nicht im command enthalten
+/// - Returns: Die Ausgabe des Befehls (stdout + stderr)
+/// - Throws: ShellCommandError wenn die Ausführung fehlschlägt
+@discardableResult
+public func cliTaskAsync(_ command: String, arguments: [String]? = nil) async throws -> String {
+    Logger.tasks.debug("Asynchrone Ausführung: \(command) \(arguments?.joined(separator: " ") ?? "")")
+    
+    return try await withCheckedThrowingContinuation { continuation in
+        // Sicher die Befehlskomponenten extrahieren
+        do {
+            let (commandLaunchPath, commandPieces) = try validateAndPrepareCommand(command, arguments: arguments)
+            
+            // Task ausführen
+            let myTask = Process()
+            let myPipe = Pipe()
+            let myErrorPipe = Pipe()
+            
+            myTask.executableURL = URL(fileURLWithPath: commandLaunchPath)
+            myTask.arguments = commandPieces
+            myTask.standardOutput = myPipe
+            myTask.standardError = myErrorPipe
+            
+            // Befehl abschließen behandeln
+            myTask.terminationHandler = { process in
+                let data = myPipe.fileHandleForReading.readDataToEndOfFile()
+                let error = myErrorPipe.fileHandleForReading.readDataToEndOfFile()
+                
+                // Ausgabe kodieren
+                guard let output = String(data: data, encoding: .utf8),
+                      let errorOutput = String(data: error, encoding: .utf8) else {
+                    continuation.resume(throwing: ShellCommandError.outputEncodingFailed)
+                    return
+                }
+                
+                // Fehlercode überprüfen
+                if process.terminationStatus != 0 {
+                    Logger.tasks.error("Befehl fehlgeschlagen: \(command) mit Exit-Code \(process.terminationStatus)")
+                    continuation.resume(throwing: ShellCommandError.executionFailed(command, process.terminationStatus))
+                } else {
+                    let result = output + errorOutput
+                    continuation.resume(returning: result)
+                }
             }
-            x += 1
+            
+            try myTask.run()
+        } catch {
+            // Fehler zurückgeben
+            continuation.resume(throwing: error)
         }
     }
+}
 
-    var commandLaunchPath = commandPieces.remove(at: 0)
-
-    // make sure the launch path is the full path -- think we're going down a rabbit hole here
-
-    if !commandLaunchPath.contains("/") {
-        let realPath = which(commandLaunchPath)
-        commandLaunchPath = realPath
-    }
-
-    // set up the NSTask instance and an NSPipe for the result
-
+/// Führt einen Shell-Befehl ohne zu warten auf Beendigung aus
+///
+/// Speziell für Befehle, die nicht normal terminieren
+///
+/// - Parameter command: Der auszuführende Befehl
+/// - Returns: Die bisherige Ausgabe des Befehls
+public func cliTaskNoTerm(_ command: String) -> String {
+    Logger.tasks.debug("Ausführung ohne Terminierung: \(command)")
+    
+    // Sicher die Befehlskomponenten extrahieren
+    let (commandLaunchPath, commandPieces) = prepareCommand(command)
+    
+    // Task ausführen ohne zu warten
     let myTask = Process()
     let myPipe = Pipe()
     let myInputPipe = Pipe()
     let myErrorPipe = Pipe()
-
-    // Setup and Launch!
-
+    
     myTask.launchPath = commandLaunchPath
     myTask.arguments = commandPieces
     myTask.standardOutput = myPipe
     myTask.standardInput = myInputPipe
     myTask.standardError = myErrorPipe
-
+    
     myTask.launch()
-
-    let data = myPipe.fileHandleForReading.readDataToEndOfFile()
-    let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
-
+    
+    guard let output = String(data: myPipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) else {
+        Logger.tasks.error("Ausgabe konnte nicht kodiert werden")
+        return ""
+    }
+    
     return output
 }
 
-
-// this is a quick routine to get the console user
-
+/// Gibt den aktuellen Konsolenbenutzer zurück
+///
+/// - Returns: Benutzername des aktuellen Konsolenbenutzers
 public func getConsoleUser() -> String {
     var uid: uid_t = 0
     var gid: gid_t = 0
-    var userName: String = ""
-
-    // use SCDynamicStore to find out who the console user is
-
-    let theResult = SCDynamicStoreCopyConsoleUser( nil, &uid, &gid)
-    userName = theResult! as String
-    return userName
+    
+    guard let theResult = SCDynamicStoreCopyConsoleUser(nil, &uid, &gid) else {
+        Logger.tasks.error("Konsolenbenutzer konnte nicht ermittelt werden")
+        return ""
+    }
+    
+    return theResult as String
 }
 
+/// Gibt die Seriennummer des Geräts zurück
+///
+/// - Returns: Die Seriennummer oder einen leeren String bei Fehler
 public func getSerial() -> String {
+    // Wert aus Cache zurückgeben, wenn verfügbar
+    if let cachedSerial = SystemInfoCache.serialNumber {
+        return cachedSerial
+    }
+    
     let platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"))
-    let serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, kIOPlatformSerialNumberKey as CFString, kCFAllocatorDefault, 0)
-    // swiftlint:disable force_cast
-    return serialNumberAsCFString?.takeUnretainedValue() as! String
-    // swiftlint:enable force_cast
+    
+    guard platformExpert > 0 else {
+        Logger.tasks.error("Platform Expert nicht gefunden")
+        return ""
+    }
+    
+    defer {
+        IOObjectRelease(platformExpert)
+    }
+    
+    guard let serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, 
+                                                                       kIOPlatformSerialNumberKey as CFString, 
+                                                                       kCFAllocatorDefault, 
+                                                                       0) else {
+        Logger.tasks.error("Seriennummer konnte nicht ausgelesen werden")
+        return ""
+    }
+    
+    guard let serialNumber = serialNumberAsCFString.takeUnretainedValue() as? String else {
+        Logger.tasks.error("Seriennummer hat ein ungültiges Format")
+        return ""
+    }
+    
+    // Wert im Cache speichern
+    SystemInfoCache.serialNumber = serialNumber
+    return serialNumber
 }
 
-// get hardware MAC addresss
-
+/// Gibt die MAC-Adresse des ersten Netzwerkinterfaces zurück
+///
+/// - Returns: Die MAC-Adresse oder einen leeren String bei Fehler
 public func getMAC() -> String {
-
+    // Wert aus Cache zurückgeben, wenn verfügbar
+    if let cachedMAC = SystemInfoCache.macAddress {
+        return cachedMAC
+    }
+    
     let myMACOutput = cliTask("/sbin/ifconfig -a").components(separatedBy: "\n")
     var myMac = ""
-
+    
     for line in myMACOutput {
         if line.contains("ether") {
-            myMac = line.replacingOccurrences(of: "ether", with: "").trimmingCharacters(in: CharacterSet.whitespaces)
+            myMac = line.replacingOccurrences(of: "ether", with: "").trimmingCharacters(in: .whitespaces)
             break
         }
     }
+    
+    // Wert im Cache speichern, wenn eine MAC gefunden wurde
+    if !myMac.isEmpty {
+        SystemInfoCache.macAddress = myMac
+    }
+    
     return myMac
 }
 
-// private function to get the path to the binary if the full path isn't given
+// MARK: - Private Hilfsfunktionen
 
+/// Bereitet einen Befehl für die Ausführung vor
+///
+/// - Parameters:
+///   - command: Der Befehl
+///   - arguments: Optionale Argumente
+/// - Returns: Tuple mit dem Pfad zum Befehl und den Argumenten
+private func prepareCommand(_ command: String, arguments: [String]? = nil) -> (String, [String]) {
+    var commandLaunchPath: String
+    var commandPieces: [String]
+    
+    if arguments == nil {
+        // Befehl in Komponenten aufteilen
+        commandPieces = command.components(separatedBy: " ")
+        
+        // Escape-Sequenzen verarbeiten
+        if command.contains("\\") {
+            var x = 0
+            
+            for line in commandPieces {
+                if line.last == "\\" {
+                    commandPieces[x] = commandPieces[x].replacingOccurrences(of: "\\", with: " ") + commandPieces.remove(at: x+1)
+                    x -= 1
+                }
+                x += 1
+            }
+        }
+        
+        commandLaunchPath = commandPieces.remove(at: 0)
+    } else {
+        commandLaunchPath = command
+        commandPieces = arguments!
+    }
+    
+    // Vollständigen Pfad für den Befehl ermitteln, wenn nötig
+    if !commandLaunchPath.contains("/") {
+        commandLaunchPath = which(commandLaunchPath)
+    }
+    
+    return (commandLaunchPath, commandPieces)
+}
+
+/// Führt einen Shell-Befehl aus
+///
+/// - Parameters:
+///   - launchPath: Pfad zur ausführbaren Datei
+///   - arguments: Befehlsargumente
+/// - Returns: Die Ausgabe des Befehls
+private func executeTask(launchPath: String, arguments: [String]) -> String {
+    let myTask = Process()
+    let myPipe = Pipe()
+    let myErrorPipe = Pipe()
+    
+    myTask.launchPath = launchPath
+    myTask.arguments = arguments
+    myTask.standardOutput = myPipe
+    myTask.standardError = myErrorPipe
+    
+    do {
+        myTask.launch()
+        myTask.waitUntilExit()
+        
+        let data = myPipe.fileHandleForReading.readDataToEndOfFile()
+        let error = myErrorPipe.fileHandleForReading.readDataToEndOfFile()
+        
+        guard let output = String(data: data, encoding: .utf8),
+              let errorOutput = String(data: error, encoding: .utf8) else {
+            Logger.tasks.error("Ausgabe konnte nicht kodiert werden")
+            return ""
+        }
+        
+        if myTask.terminationStatus != 0 {
+            Logger.tasks.error("Befehl fehlgeschlagen mit Exit-Code \(myTask.terminationStatus): \(launchPath) \(arguments.joined(separator: " "))")
+        }
+        
+        return output + errorOutput
+    } catch {
+        Logger.tasks.error("Fehler bei Befehlsausführung: \(error.localizedDescription)")
+        return ""
+    }
+}
+
+/// Validiert und bereitet einen Befehl für die Ausführung vor
+///
+/// - Parameters:
+///   - command: Der Befehl
+///   - arguments: Optionale Argumente
+/// - Returns: Tuple mit dem Pfad zum Befehl und den Argumenten
+/// - Throws: ShellCommandError wenn der Befehl ungültig ist
+private func validateAndPrepareCommand(_ command: String, arguments: [String]? = nil) throws -> (String, [String]) {
+    if command.isEmpty {
+        throw ShellCommandError.invalidCommand
+    }
+    
+    let (launchPath, args) = prepareCommand(command, arguments: arguments)
+    
+    // Überprüfen, ob der Befehl existiert
+    if launchPath.isEmpty || !FileManager.default.fileExists(atPath: launchPath) {
+        throw ShellCommandError.commandNotFound(command)
+    }
+    
+    return (launchPath, args)
+}
+
+/// Ermittelt den vollständigen Pfad eines Befehls
+///
+/// - Parameter command: Der zu suchende Befehl
+/// - Returns: Vollständiger Pfad zum Befehl oder leerer String bei Fehler
 private func which(_ command: String) -> String {
     let task = Process()
     task.launchPath = "/usr/bin/which"
     task.arguments = [command]
-
+    
     let whichPipe = Pipe()
     task.standardOutput = whichPipe
-    task.launch()
-
-    let data = whichPipe.fileHandleForReading.readDataToEndOfFile()
-    let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
     
-    if output == "" {
-        Logger.tasks.error("Binary doesn't exist")
+    do {
+        task.launch()
+        task.waitUntilExit()
+        
+        let data = whichPipe.fileHandleForReading.readDataToEndOfFile()
+        guard let output = String(data: data, encoding: .utf8) else {
+            Logger.tasks.error("Which-Ausgabe konnte nicht kodiert werden")
+            return ""
+        }
+        
+        let result = output.components(separatedBy: "\n").first ?? ""
+        
+        if result.isEmpty {
+            Logger.tasks.error("Binary existiert nicht: \(command)")
+        }
+        
+        return result
+    } catch {
+        Logger.tasks.error("Fehler bei which-Befehl: \(error.localizedDescription)")
+        return ""
     }
-    
-    return output.components(separatedBy: "\n").first!
-    
 }
diff --git a/Network Share Mounter/lookups/SRVRecord.swift b/Network Share Mounter/lookups/SRVRecord.swift
index c5fc3117ffdf07a29938d5177d63769f9ee428e9..eb2c77689123479a512e21e4070cdd7bfc130ab8 100644
--- a/Network Share Mounter/lookups/SRVRecord.swift	
+++ b/Network Share Mounter/lookups/SRVRecord.swift	
@@ -15,29 +15,20 @@ public struct SRVResult {
     
     /// Sorts SRV records by weight and returns target hostnames
     /// - Returns: Array of target hostnames sorted by weight, nil if no records exist
-    /// - Note: Uses bubble sort algorithm for simplicity. Consider using Swift's sort() for better performance
+    /// - Note: Uses Swift's native sort for optimal performance
     func sortByWeight() -> [String]? {
-        guard !SRVRecords.isEmpty else { return nil}
+        guard !SRVRecords.isEmpty else { return nil }
         
-        var data_set = SRVRecords
-        var swap = true
-        while swap == true {
-            swap = false
-            for i in 0..<data_set.count - 1 {
-                if data_set[i].weight > data_set[i + 1].weight {
-                    let temp = data_set [i + 1]
-                    data_set [i + 1] = data_set[i]
-                    data_set[i] = temp
-                    swap = true
-                }
-            }
-        }
-        return data_set.map({ $0.target })
+        return SRVRecords
+            .sorted { $0.weight < $1.weight }
+            .map { $0.target }
     }
 }
 
 // MARK: - CustomStringConvertible Implementation
 extension SRVResult: CustomStringConvertible {
+    /// Returns a string representation of the SRV result
+    /// - Returns: A formatted string containing query and record information
     public var description: String {
         var result = "Query for: \(query)"
         result += "\n\tRecord Count: \(SRVRecords.count)"
@@ -54,7 +45,7 @@ public struct SRVRecord: Codable, Equatable {
     let priority: Int
     /// Relative weight for records with same priority
     let weight: Int
-    /// TCP/UDP port number of the service
+    /// TCP/UDP port number of the service (valid range: 1-65535)
     let port: Int
     /// Hostname of the target machine
     let target: String
@@ -62,36 +53,45 @@ public struct SRVRecord: Codable, Equatable {
     /// Initializes an SRV record from raw DNS response data
     /// - Parameter data: Raw DNS response bytes
     /// - Returns: nil if data is invalid or too short
-    /// - Note: Current implementation has basic Unicode control character handling
+    /// - Note: Implements robust Unicode handling for hostnames
     init?(data: Data) {
         guard data.count > 8 else { return nil }
         
-        var workingTarget = ""
-        
+        // Parse priority, weight, and port
         priority = Int(data[0]) * 256 + Int(data[1])
         weight = Int(data[2]) * 256 + Int(data[3])
         port = Int(data[4]) * 256 + Int(data[5])
         
-        // Skip byte 6 (Unicode control character)
+        // Validate port number
+        guard port > 0 && port <= 65535 else { return nil }
         
-        // Parse hostname from remaining bytes
-        // TODO: Consider using a more robust Unicode handling approach
-        for byte in data[7...(data.count - 1)] {
-            if let char = String(data: Data([byte]), encoding: .utf8) {
-                switch char {
-                case "\u{03}", "\u{04}", "\u{05}", "\0":
-                    workingTarget += "."
-                default:
-                    workingTarget += char
-                }
+        // Parse hostname with improved Unicode handling
+        var workingTarget = ""
+        var currentByte = 7
+        
+        while currentByte < data.count {
+            let byte = data[currentByte]
+            
+            // Handle control characters and dots
+            if byte == 0x00 || (byte >= 0x03 && byte <= 0x05) {
+                workingTarget += "."
+            } else if let char = String(data: Data([byte]), encoding: .utf8) {
+                workingTarget += char
             }
+            currentByte += 1
         }
+        
+        // Validate target hostname
+        guard !workingTarget.isEmpty else { return nil }
+        
         target = workingTarget
     }
 }
 
 // MARK: - CustomStringConvertible Implementation
 extension SRVRecord: CustomStringConvertible {
+    /// Returns a string representation of the SRV record
+    /// - Returns: A formatted string containing target, priority, weight, and port
     public var description: String {
         "\(target) \(priority) \(weight) \(port)"
     }
diff --git a/Network Share Mounter/lookups/SRVResolver.swift b/Network Share Mounter/lookups/SRVResolver.swift
index ab2c2b2ebb075205be29f399883d2235dab5e309..7f99aae650b4a04c268cee29dd52ddf0931a31c1 100644
--- a/Network Share Mounter/lookups/SRVResolver.swift	
+++ b/Network Share Mounter/lookups/SRVResolver.swift	
@@ -14,6 +14,10 @@ import Combine
 /// Enum representing possible errors during SRV resolution.
 public enum SRVResolverError: String, Error, Codable {
     case unableToComplete = "Unable to complete lookup"
+    case invalidQuery = "Invalid query string"
+    case socketError = "Failed to create socket"
+    case timeout = "DNS lookup timed out"
+    case serviceError = "DNS service error"
 }
 
 /// Type alias for the result of an SRV resolution.
@@ -23,27 +27,43 @@ public typealias SRVResolverResult = Result<SRVResult, SRVResolverError>
 public typealias SRVResolverCompletion = (SRVResolverResult) -> Void
 
 /// Class responsible for resolving SRV records.
+/// 
+/// This class handles DNS-SRV record resolution using the dnssd framework.
+/// It provides asynchronous resolution with timeout handling and proper resource cleanup.
 class SRVResolver {
+    /// Dispatch queue for handling DNS operations
     private let queue = DispatchQueue(label: "SRVResolution")
+    
+    /// Source for reading from the DNS socket
     private var dispatchSourceRead: DispatchSourceRead?
+    
+    /// Timer for handling timeouts
     private var timeoutTimer: DispatchSourceTimer?
+    
+    /// Reference to the DNS service
     private var serviceRef: DNSServiceRef?
+    
+    /// Socket file descriptor
     private var socket: dnssd_sock_t = -1
+    
+    /// The current DNS query string
     private var query: String?
     
-    /// Default timeout for DNS lookups.
-    private let timeout = TimeInterval(5)
+    /// Default timeout for DNS lookups in seconds
+    private let timeout: TimeInterval = 5
     
+    /// Array to store resolved SRV records
     var results = [SRVRecord]()
+    
+    /// Completion handler for the resolution process
     var completion: SRVResolverCompletion?
     
-    /// Callback function for processing DNS results.
-    let queryCallback: DNSServiceQueryRecordReply = { (sdRef, flags, interfaceIndex, errorCode, fullname, rrtype, rrclass, rdlen, rdata, ttl, context) -> Void in
-        
+    /// Callback function for processing DNS results
+    private let queryCallback: DNSServiceQueryRecordReply = { (sdRef, flags, interfaceIndex, errorCode, fullname, rrtype, rrclass, rdlen, rdata, ttl, context) -> Void in
         guard let context = context else { return }
         
         let resolver: SRVResolver = SRVResolver.bridge(context)
-
+        
         if let data = rdata?.assumingMemoryBound(to: UInt8.self),
            let record = SRVRecord(data: Data(bytes: data, count: Int(rdlen))) {
             resolver.results.append(record)
@@ -54,55 +74,69 @@ class SRVResolver {
         }
     }
     
-    /// Bridges an Objective-C object to a Swift pointer.
-    static func bridge<T: AnyObject>(_ obj: T) -> UnsafeMutableRawPointer {
+    /// Bridges an Objective-C object to a Swift pointer
+    /// - Parameter obj: The object to bridge
+    /// - Returns: An UnsafeMutableRawPointer containing the bridged object
+    private static func bridge<T: AnyObject>(_ obj: T) -> UnsafeMutableRawPointer {
         return Unmanaged.passUnretained(obj).toOpaque()
     }
     
-    /// Bridges a Swift pointer back to an Objective-C object.
-    static func bridge<T: AnyObject>(_ ptr: UnsafeMutableRawPointer) -> T {
+    /// Bridges a Swift pointer back to an Objective-C object
+    /// - Parameter ptr: The pointer to bridge
+    /// - Returns: The bridged object
+    private static func bridge<T: AnyObject>(_ ptr: UnsafeMutableRawPointer) -> T {
         return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
     }
     
-    /// Handles a failed SRV resolution.
-    func fail() {
+    /// Handles a failed SRV resolution
+    private func fail() {
         stopQuery()
         completion?(.failure(.unableToComplete))
     }
     
-    /// Handles a successful SRV resolution.
-    func success() {
+    /// Handles a successful SRV resolution
+    private func success() {
         stopQuery()
         let result = SRVResult(SRVRecords: results, query: query ?? "Unknown Query")
         completion?(.success(result))
     }
     
-    /// Stops the DNS query and cleans up resources.
+    /// Stops the DNS query and cleans up resources
     private func stopQuery() {
         timeoutTimer?.cancel()
+        timeoutTimer = nil
+        
         dispatchSourceRead?.cancel()
+        dispatchSourceRead = nil
+        
         if let serviceRef = serviceRef {
             DNSServiceRefDeallocate(serviceRef)
             self.serviceRef = nil
         }
+        
+        if socket != -1 {
+            close(socket)
+            socket = -1
+        }
     }
     
-    /// Initiates the SRV resolution process.
+    /// Initiates the SRV resolution process
     /// - Parameters:
-    ///   - query: The DNS query string.
-    ///   - completion: The completion handler to call when the resolution is complete.
+    ///   - query: The DNS query string
+    ///   - completion: The completion handler to call when the resolution is complete
     func resolve(query: String, completion: @escaping SRVResolverCompletion) {
         self.completion = completion
         self.query = query
+        
         guard let namec = query.cString(using: .utf8) else {
-            fail()
+            completion(.failure(.invalidQuery))
             return
         }
         
         let result = DNSServiceQueryRecord(
             &serviceRef,
             kDNSServiceFlagsReturnIntermediates,
-            0, // query on all interfaces.
+            0, // query on all interfaces
             namec,
             UInt16(kDNSServiceType_SRV),
             UInt16(kDNSServiceClass_IN),
@@ -113,46 +147,60 @@ class SRVResolver {
         switch result {
         case DNSServiceErrorType(kDNSServiceErr_NoError):
             guard let sdRef = serviceRef else {
-                fail()
+                completion(.failure(.serviceError))
                 return
             }
             
             socket = DNSServiceRefSockFD(sdRef)
             
             guard socket != -1 else {
-                fail()
+                completion(.failure(.socketError))
                 return
             }
             
-            dispatchSourceRead = DispatchSource.makeReadSource(fileDescriptor: socket, queue: queue)
-            
-            dispatchSourceRead?.setEventHandler(handler: {
-                let res = DNSServiceProcessResult(sdRef)
-                if res != kDNSServiceErr_NoError {
-                    self.fail()
-                }
-            })
-            
-            dispatchSourceRead?.setCancelHandler(handler: {
-                if let serviceRef = self.serviceRef {
-                    DNSServiceRefDeallocate(serviceRef)
-                }
-            })
-            
-            dispatchSourceRead?.resume()
-            
-            timeoutTimer = DispatchSource.makeTimerSource(flags: [], queue: queue)
-            
-            timeoutTimer?.setEventHandler(handler: {
-                self.fail()
-            })
-            
-            let deadline = DispatchTime.now() + timeout
-            timeoutTimer?.schedule(deadline: deadline, repeating: .infinity, leeway: .never)
-            timeoutTimer?.resume()
+            setupDispatchSource(for: sdRef)
+            setupTimeoutTimer()
             
         default:
-            fail()
+            completion(.failure(.serviceError))
+        }
+    }
+    
+    /// Sets up the dispatch source for reading from the socket
+    /// - Parameter sdRef: The DNS service reference
+    private func setupDispatchSource(for sdRef: DNSServiceRef) {
+        dispatchSourceRead = DispatchSource.makeReadSource(fileDescriptor: socket, queue: queue)
+        
+        dispatchSourceRead?.setEventHandler { [weak self] in
+            guard let self = self else { return }
+            let res = DNSServiceProcessResult(sdRef)
+            if res != kDNSServiceErr_NoError {
+                self.fail()
+            }
         }
+        
+        dispatchSourceRead?.setCancelHandler { [weak self] in
+            guard let self = self else { return }
+            if let serviceRef = self.serviceRef {
+                DNSServiceRefDeallocate(serviceRef)
+            }
+        }
+        
+        dispatchSourceRead?.resume()
+    }
+    
+    /// Sets up the timeout timer
+    private func setupTimeoutTimer() {
+        timeoutTimer = DispatchSource.makeTimerSource(flags: [], queue: queue)
+        
+        timeoutTimer?.setEventHandler { [weak self] in
+            guard let self = self else { return }
+            self.completion?(.failure(.timeout))
+            self.stopQuery()
+        }
+        
+        let deadline = DispatchTime.now() + timeout
+        timeoutTimer?.schedule(deadline: deadline, repeating: .infinity, leeway: .never)
+        timeoutTimer?.resume()
     }
 }
diff --git a/Network Share Mounter/preferences/FAU.swift b/Network Share Mounter/preferences/FAU.swift
index edcb344baad96e149f04b43cbb8e9583ed095502..d945262661d54bdbc994ffb0a2a622270c7a9254 100644
--- a/Network Share Mounter/preferences/FAU.swift	
+++ b/Network Share Mounter/preferences/FAU.swift	
@@ -10,85 +10,182 @@ import Foundation
 import OSLog
 import dogeADAuth
 
+/// Constants specific to FAU (Friedrich-Alexander-Universität) authentication
 struct FAU {
+    /// Service name for FAU IdM keychain entries
     static let keyChainServiceFAUIdM = "FAU IdM account"
+    
+    /// Comment for keychain entries
     static let keyChainComment = "FAU IdM credentials for Kerberos ticket management"
-    static let kerberosRealm = "fauad.fau.de"  // this is intentiopnally set to lowercase
+    
+    /// Kerberos realm for FAU (intentionally lowercase)
+    static let kerberosRealm = "fauad.fau.de"
+    
+    /// Logo image name for authentication dialogs
     static let authenticationDialogImage = "FAUMac_Logo_512"
 }
 
+/// Errors that can occur during migration processes
+enum MigrationError: Error, LocalizedError {
+    case keychainAccessFailed
+    case migrationFailed
+    
+    var errorDescription: String? {
+        switch self {
+        case .keychainAccessFailed:
+            return "Failed to access keychain entries"
+        case .migrationFailed:
+            return "Migration of user account failed"
+        }
+    }
+}
+
+/// Manages migration of user accounts from legacy format to new format
 class Migrator: dogeADUserSessionDelegate {
+    /// Current authentication session
     var session: dogeADSession?
+    
+    /// Access to user preferences
     var prefs = PreferenceManager()
+    
+    /// Shared accounts manager
     let accountsManager = AccountsManager.shared
     
+    /// Called when authentication succeeds
+    /// 
+    /// Switches to the authenticated Kerberos principal and posts a notification
     func dogeADAuthenticationSucceded() async {
+        guard let principal = self.session?.userPrincipal else {
+            Logger.FAU.error("Authentication succeeded but userPrincipal is nil")
+            return
+        }
+        
         do {
-            _ = try await cliTask("kswitch -p \(String(describing: self.session?.userPrincipal))")
+            let result = try await cliTaskAsync("kswitch -p \(principal)")
+            Logger.FAU.debug("Successfully switched Kerberos principal: \(result)")
         } catch {
             Logger.FAU.error("kswitch -p failed: \(error.localizedDescription)")
+            // Continue despite error, as authentication still succeeded
         }
-        NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["krbAuthenticated": MounterError.krbAuthSuccessful])
+        
+        NotificationCenter.default.post(
+            name: .nsmNotification,
+            object: nil,
+            userInfo: ["krbAuthenticated": MounterError.krbAuthSuccessful]
+        )
+        
         await session?.userInfo()
     }
     
+    /// Called when authentication fails
+    ///
+    /// - Parameters:
+    ///   - error: The error that occurred during authentication
+    ///   - description: Description of the error
     func dogeADAuthenticationFailed(error: dogeADAuth.dogeADSessionError, description: String) {
-        Logger.FAU.debug("Auth failed after FAU user migration, \(description, privacy: .public)")
+        Logger.FAU.error("Authentication failed after FAU user migration: \(description)")
     }
     
+    /// Called when user information is retrieved
+    ///
+    /// - Parameter user: The retrieved user record
     func dogeADUserInformation(user: dogeADAuth.ADUserRecord) {
-        Logger.FAU.debug("User info: \(user.userPrincipal, privacy: .public)")
+        Logger.FAU.debug("User information received for: \(user.userPrincipal, privacy: .public)")
     }
     
-    /// get keychain entry, create new user and start kerberos authentication
+    /// Migrates legacy keychain entries to the new format
+    ///
+    /// This method retrieves existing keychain entries from Prefix Assistant,
+    /// creates a new user account, and initiates Kerberos authentication.
     func migrate() async {
+        Logger.FAU.debug("Starting migration of FAU user accounts")
+        
+        let keyUtil = KeychainManager()
+        
         do {
-            // get existing prefix assistant keychain entry
-            let keyUtil = KeychainManager()
-            let keyChainEntries = try keyUtil.retrieveAllEntries(forService: FAU.keyChainServiceFAUIdM, accessGroup: Defaults.keyChainAccessGroup)
-            // use the first found entry (should also be the only one)
-            if let firstAccount = keyChainEntries.first {
-                // call the keychain migration
-                if migrateKeychainEntry(forUsername: firstAccount.username, andPassword: firstAccount.password, toRealm: FAU.kerberosRealm) {
-                    // create new DogeAccount (at FAU the migrated account will always stored in keychain)
-                    let newAccount = DogeAccount(displayName: firstAccount.username, upn: firstAccount.username + "@" + FAU.kerberosRealm, hasKeychainEntry: true)
-                    await accountsManager.addAccount(account: newAccount)
-                    // start kerberos authentication
-                    self.session = dogeADSession.init(domain: FAU.kerberosRealm, user: firstAccount.username + "@" + FAU.kerberosRealm)
-                    self.session?.setupSessionFromPrefs(prefs: prefs)
-                    self.session?.userPass = firstAccount.password
-                    self.session?.delegate = self
-                    await self.session?.authenticate()
-                    Logger.FAU.debug("FAU user migrated, NSM account created and authenticated.")
-                } else {
-                    Logger.FAU.debug("FAU user migration failed.")
-                }
+            // Get existing prefix assistant keychain entries
+            let keyChainEntries = try keyUtil.retrieveAllEntries(
+                forService: FAU.keyChainServiceFAUIdM,
+                accessGroup: Defaults.keyChainAccessGroup
+            )
+            
+            guard let firstAccount = keyChainEntries.first else {
+                Logger.FAU.notice("No accounts found to migrate")
+                return
+            }
+            
+            // Migrate the keychain entry
+            let migrationSuccessful = await migrateKeychainEntry(
+                forUsername: firstAccount.username,
+                andPassword: firstAccount.password,
+                toRealm: FAU.kerberosRealm
+            )
+            
+            if migrationSuccessful {
+                // Create new DogeAccount
+                let upn = firstAccount.username + "@" + FAU.kerberosRealm
+                let newAccount = DogeAccount(
+                    displayName: firstAccount.username,
+                    upn: upn,
+                    hasKeychainEntry: true
+                )
+                
+                await accountsManager.addAccount(account: newAccount)
+                
+                // Start Kerberos authentication
+                self.session = dogeADSession(domain: FAU.kerberosRealm, user: upn)
+                self.session?.setupSessionFromPrefs(prefs: prefs)
+                self.session?.userPass = firstAccount.password
+                self.session?.delegate = self
+                
+                await self.session?.authenticate()
+                Logger.FAU.info("FAU user migrated, NSM account created and authenticated")
+            } else {
+                Logger.FAU.error("FAU user migration failed")
             }
         } catch {
-            Logger.FAU.error("Keychain access failed, FAU user migration failed.")
+            Logger.FAU.error("Keychain access failed: \(error.localizedDescription)")
         }
     }
     
-    /// retrieve keychain entry for a given userName, append kerberos realm and save into
-    /// a new keychain entry
-    /// - Parameter forUsername: ``username`` login for share
-    /// - Parameter toRealm: ``realm`` kerberos realm appended to userName (defaults to FAU.kerberosRealm
-    func migrateKeychainEntry(forUsername: String, andPassword pass: String, toRealm realm: String = FAU.kerberosRealm) -> Bool {
+    /// Migrates a keychain entry by adding the Kerberos realm and saving to a new entry
+    ///
+    /// - Parameters:
+    ///   - forUsername: Login username for share
+    ///   - andPassword: Password for the account
+    ///   - toRealm: Kerberos realm to append (defaults to FAU.kerberosRealm)
+    /// - Returns: Whether migration was successful
+    func migrateKeychainEntry(
+        forUsername: String,
+        andPassword pass: String,
+        toRealm realm: String = FAU.kerberosRealm
+    ) async -> Bool {
         let pwm = KeychainManager()
         var userName = forUsername.removeDomain()
+        
+        userName.appendDomain(domain: realm.lowercased())
+        
         do {
-            userName.appendDomain(domain: realm.lowercased())
-            try pwm.saveCredential(forUsername: userName,
-                                   andPassword: pass,
-                                   withService: Defaults.keyChainService,
-                                   accessGroup: Defaults.keyChainAccessGroup,
-                                   comment: "FAU IdM Kerberos Account for Network Share Mounter")
-            Logger.FAU.debug("Prefix Assistant keychain entry migration for user \(userName, privacy: .public) done")
+            try pwm.saveCredential(
+                forUsername: userName,
+                andPassword: pass,
+                withService: Defaults.keyChainService,
+                accessGroup: Defaults.keyChainAccessGroup,
+                comment: "FAU IdM Kerberos Account for Network Share Mounter"
+            )
+            
+            Logger.FAU.debug("Prefix Assistant keychain entry migration for user \(userName, privacy: .public) completed")
             prefs.set(for: .keyChainPrefixManagerMigration, value: true)
-            NotificationCenter.default.post(name: .nsmNotification, object: nil, userInfo: ["ClearError": MounterError.noError])
+            
+            NotificationCenter.default.post(
+                name: .nsmNotification,
+                object: nil,
+                userInfo: ["ClearError": MounterError.noError]
+            )
+            
             return true
         } catch {
-            Logger.FAU.error("Could not save Prefix Assistant migrated keychain entry for user: \(userName, privacy: .public)")
+            Logger.FAU.error("Could not save migrated keychain entry: \(error.localizedDescription)")
             return false
         }
     }
diff --git a/Network Share Mounter/preferences/PreferenceKeys.swift b/Network Share Mounter/preferences/PreferenceKeys.swift
index 34ca053eb38f462ecd18f2874564c4112d2b7ebb..c7b05ce4b2b122a6787724fe87714afbbd0cf6c2 100644
--- a/Network Share Mounter/preferences/PreferenceKeys.swift	
+++ b/Network Share Mounter/preferences/PreferenceKeys.swift	
@@ -8,222 +8,261 @@
 //
 
 import Foundation
+import OSLog
 
+/// Keys used for accessing user preferences in the application
+///
+/// This enumeration defines all preference keys used throughout the application.
+/// Each key corresponds to a specific setting that can be stored in and retrieved from `UserDefaults`.
 enum PreferenceKeys: String, CaseIterable {
     
     typealias RawValue = String
     
+    // MARK: - User Account Settings
+    
+    /// List of user accounts
     case accounts = "Accounts"
-//    case actionItemOnly = "ActionItemOnly"
+    
+    /// Active Directory domain
     case aDDomain = "ADDomain"
-//    case aDSite = "ADSite"
+    
+    /// Active Directory domain controller
     case aDDomainController = "ADDomainController"
-//    case allowEAPOL = "AllowEAPOL"
+    
+    /// Dictionary of all user information
     case allUserInformation = "AllUserInformation"
-//    case autoAddAccounts = "AutoAddAccounts"
-//    case autoConfigure = "AutoConfigure"
-//    case autoRenewCert = "AutoRenewCert"
-//    case changePasswordCommand = "ChangePasswordCommand"
-//    case changePasswordType = "ChangePasswordType"
-//    case changePasswordOptions = "ChangePasswordOptions"
-//    case caribouTime = "CaribouTime"
-//    case cleanCerts = "CleanCerts"
-//    case configureChrome = "ConfigureChrome"
-//    case configureChromeDomain = "ConfigureChromeDomain"
+    
+    /// Custom LDAP attributes to query
     case customLDAPAttributes = "CustomLDAPAttributes"
+    
+    /// Results of custom LDAP attribute queries
     case customLDAPAttributesResults = "CustomLDAPAttributesResults"
-//    case deadLDAPKillTickets = "DeadLDAPKillTickets"
+    
+    /// User's display name
     case displayName = "DisplayName"
-//    case dontMatchKerbPrefs = "DontMatchKerbPrefs"
-//    case dontShowWelcome = "DontShowWelcome"
-//    case dontShowWelcomeDefaultOn = "DontShowWelcomeDefaultOn"
-//    case exportableKey = "ExportableKey"
-//    case firstRunDone = "FirstRunDone"
-//    case getCertAutomatically = "GetCertificateAutomatically"
-//    case getHelpType = "GetHelpType"
-//    case getHelpOptions = "GetHelpOptions"
-//    case groups = "Groups"
-//    case hicFix = "HicFix"
-//    case hideAbout = "HideAbout"
-//    case hideAccounts = "HideAccounts"
-//    case hideExpiration = "HideExpiration"
-//    case hideExpirationMessage = "HideExpirationMessage"
-//    case hideCertificateNumber = "HideCertificateNumber"
-//    case hideHelp = "HideHelp"
-//    case hideGetSoftware = "HideGetSoftware"
+    
+    /// Whether to hide the last user in UI
     case hideLastUser = "HideLastUser"
-//    case hideLockScreen = "HideLockScreen"
-//    case hideRenew = "HideRenew"
-//    case hidePrefs = "HidePrefs"
-//    case hideSignIn = "HideSignIn"
-//    case hideTickets = "HideTickets"
-//    case hideQuit = "HideQuit"
-//    case hideSignOut = "HideSignOut"
-//    case homeAppendDomain = "HomeAppendDomain"
-//    case iconOff = "IconOff"
-//    case iconOffDark = "IconOffDark"
-//    case iconOn = "IconOn"
-//    case iconOnDark = "IconOnDark"
+    
+    /// Kerberos realm for authentication
     case kerberosRealm = "kerberosRealm"
-//    case keychainItems = "KeychainItems"
-//    case keychainItemsInternet = "KeychainItemsInternet"
-//    case keychainItemsCreateSerial = "KeychainItemsCreateSerial"
-//    case keychainItemsDebug = "KeychainItemsDebug"
-//    case keychainMinderWindowTitle = "KeychainMinderWindowTitle"
-//    case keychainMinderWindowMessage = "KeychainMinderWindowMessage"
-//    case keychainMinderShowReset = "KeychainMinderShowReset"
-//    case keychainPasswordMatch = "KeychainPasswordMatch"
-//    case lastCertificateExpiration = "LastCertificateExpiration"
-//    case lightsOutIKnowWhatImDoing = "LightsOutIKnowWhatImDoing"
-//    case loginComamnd = "LoginComamnd"
-//    case loginItem = "LoginItem"
+    
+    /// Whether LDAP queries should be anonymous
     case ldapAnonymous = "LDAPAnonymous"
-//    case lDAPSchema = "LDAPSchema"
+    
+    /// List of LDAP servers to query
     case lDAPServerList = "LDAPServerList"
-//    case lDAPServerListDeny = "LDAPServerListDeny"
+    
+    /// Whether to use SSL for LDAP connections
     case lDAPoverSSL = "LDAPOverSSL"
-//    case lDAPOnly = "LDAPOnly"
-//    case lDAPType = "LDAPType"
-//    case localPasswordSync = "LocalPasswordSync"
-//    case localPasswordSyncDontSyncLocalUsers = "LocalPasswordSyncDontSyncLocalUsers"
-//    case localPasswordSyncDontSyncNetworkUsers = "LocalPasswordSyncDontSyncNetworkUsers"
-//    case localPasswordSyncOnMatchOnly = "LocalPasswordSyncOnMatchOnly"
-//    case lockedKeychainCheck = "LockedKeychainCheck"
+    
+    /// Last logged in user
     case lastUser = "LastUser"
-//    case lastPasswordWarning = "LastPasswordWarning"
-//    case lastPasswordExpireDate = "LastPasswordExpireDate"
-//    case loginLogo = "LoginLogo"
-//    
-//    case messageLocalSync = "MessageLocalSync"
-//    case messageNotConnected = "MessageNotConnected"
-//    case messageUPCAlert = "MessageUPCAlert"
-//    case messagePasswordChangePolicy = "MessagePasswordChangePolicy"
-//    case mountSharesWithFinder = "MountSharesWithFinder"
-//    case passwordExpirationDays = "PasswordExpirationDays"
-//    case passwordExpireAlertTime = "PasswordExpireAlertTime"
-//    case passwordExpireCustomAlert = "PasswordExpireCustomAlert"
-//    case passwordExpireCustomWarnTime = "PasswordExpireCustomWarnTime"
-//    case passwordExpireCustomAlertTime = "PasswordExpireCustomAlertTime"
-//    case passwordPolicy = "PasswordPolicy"
-//    case persistExpiration = "PersistExpiration"
-//    case profileDone = "ProfileDone"
-//    case profileWait = "ProfileWait"
-//    case recursiveGroupLookup = "RecursiveGroupLookup"
-//    case renewTickets = "RenewTickets"
-//    case showHome = "ShowHome"
-//    case secondsToRenew = "SecondsToRenew"
-//    case shareReset = "ShareReset"        // clean listing of shares between runs
-//    case signInCommand = "SignInCommand"
-//    case signInWindowAlert = "SignInWindowAlert"
-//    case signInWindowAlertTime = "SignInWindowAlertTime"
-//    case signInWindowOnLaunch = "SignInWindowOnLaunch"
-//    case signInWindowOnLaunchExclusions = "SignInWindowOnLaunchExclusions"
-//    case signedIn = "SignedIn"
-//    case signOutCommand = "SignOutCommand"
+    
+    /// Whether to use single user mode
     case singleUserMode = "SingleUserMode"
-//    case siteIgnore = "SiteIgnore"
-//    case siteForce = "SiteForce"
-//    case slowMount = "SlowMount"
-//    case slowMountDelay = "SlowMountDelay"
-//    case stateChangeAction = "StateChangeAction"
-//    case switchKerberosUser = "SwitchKerberosUser"
-//    case template = "Template"
-//    case titleSignIn = "TitleSignIn"
-//    case uPCAlert = "UPCAlert"
-//    case uPCAlertAction = "UPCAlertAction"
+    
+    /// User's Common Name (CN)
     case userCN = "UserCN"
+    
+    /// User's group memberships
     case userGroups = "UserGroups"
+    
+    /// User's Kerberos principal
     case userPrincipal = "UserPrincipal"
+    
+    /// User's home directory
     case userHome = "UserHome"
+    
+    /// User's password expiration date
     case userPasswordExpireDate = "UserPasswordExpireDate"
-//    case userCommandTask1 = "UserCommandTask1"
-//    case userCommandName1 = "UserCommandName1"
-//    case userCommandHotKey1 = "UserCommandHotKey1"
+    
+    /// Date when user's password was last set
     case userPasswordSetDate = "UserPasswordSetDate"
+    
+    /// Whether to use Keychain for password storage
     case useKeychain = "UseKeychain"
-//    case useKeychainPrompt = "UseKeychainPrompt"
-//    case userAging = "UserAging"
-//    case userAttributes = "UserAttributes"
+    
+    /// User's email address
     case userEmail = "UserEmail"
+    
+    /// User's first name
     case userFirstName = "UserFirstName"
+    
+    /// User's full name
     case userFullName = "UserFullName"
+    
+    /// User's last name
     case userLastName = "UserLastName"
+    
+    /// Last time user information was checked
     case userLastChecked = "UserLastChecked"
+    
+    /// User's short name (username)
     case userShortName = "UserShortName"
-//    case userSwitch = "UserSwitch"
+    
+    /// User's User Principal Name (UPN)
     case userUPN = "UserUPN"
-//    case verbose = "Verbose"
-//    case wifiNetworks = "WifiNetworks"
-//    case windowSignIn = "WindowSignIn"
-//    case x509CA = "X509CA"
-//    case x509Name = "X509Name"
     
+    // MARK: - Application Settings
+    
+    /// Whether to unmount shares on application exit
     case unmountOnExit = "unmountOnExit"
+    
+    /// URL for help documentation
     case helpURL = "helpURL"
+    
+    /// Whether user can change autostart setting
     case canChangeAutostart = "canChangeAutostart"
+    
+    /// Whether user can quit the application
     case canQuit = "canQuit"
+    
+    /// Whether application starts automatically at login
     case autostart = "autostart"
+    
+    /// Whether auto-updater is enabled
     case enableAutoUpdater = "enableAutoUpdater"
+    
+    /// Whether to automatically check for updates
     case autoUpdate = "autoUpdate"
+    
+    /// Directory for cleanup operations
     case cleanupLocationDirectory = "cleanupLocationDirectory"
+    
+    /// Unique identifier for the application instance
     case UUID = "UUID"
+    
+    /// Override for username if local and remote usernames differ
+    case usernameOverride = "usernameOverride"
+    
+    /// Whether to send diagnostic data
+    case sendDiagnostics = "sendDiagnostics"
+    
+    /// Whether to use new default location for mounts
+    case useNewDefaultLocation = "useNewDefaultLocation"
+    
+    // MARK: - Network Share Settings
+    
+    /// List of network shares
     case networkSharesKey = "networkShares"
+    
+    /// List of managed network shares (from MDM)
     case managedNetworkSharesKey = "managedNetworkShares"
+    
+    /// Authentication type for shares
     case authType = "authType"
+    
+    /// Network share path
     case networkShare = "networkShare"
+    
+    /// Mount point for shares
     case mountPoint = "mountPoint"
+    
+    /// Username for share authentication
     case username = "username"
+    
+    /// List of custom network shares
     case customSharesKey = "customNetworkShares"
+    
+    /// List of user-specific network shares
     case userNetworkShares = "userNetworkShares"
+    
+    /// Location for network shares
     case location = "location"
+    
+    // MARK: - UI Settings
+    
+    /// Image name for authentication dialog
     case authenticationDialogImage = "authenticationDialogImage"
+    
+    /// Service name for keychain entries
     case keyChainService = "keyChainService"
+    
+    /// Label for keychain entries
     case keyChainLabel = "keyChainLabel"
+    
+    /// Comment for keychain entries
     case keyChainComment = "keyChainComment"
+    
+    /// Whether keychain migration from Prefix Manager is done
     case keyChainPrefixManagerMigration = "keyChainPrefixManagerMigration"
-    case useNewDefaultLocation = "useNewDefaultLocation"
     
-    // used to manually override %USERNAME% if local and remoter user names differ
-    case usernameOverride = "usernameOverride"
-    // used to define if diagnostic data should be sent to the FAUmac team
-    case sendDiagnostics = "sendDiagnostics"
+    // MARK: - Menu Items
     
-    // control menu items
+    /// Whether to show Quit menu item
     case menuQuit = "menuQuit"
+    
+    /// Whether to show About menu item
     case menuAbout = "menuAbout"
+    
+    /// Whether to show Connect Shares menu item
     case menuConnectShares = "menuConnectShares"
+    
+    /// Whether to show Disconnect Shares menu item
     case menuDisconnectShares = "menuDisconnectShares"
+    
+    /// Whether to show Check Updates menu item
     case menuCheckUpdates = "menuCheckUpdates"
+    
+    /// Whether to show Show Shares Mount Directory menu item
     case menuShowSharesMountDir = "menuShowSharesMountDir"
+    
+    /// Whether to show Show Shares menu item
     case menuShowShares = "menuShowShares"
+    
+    /// Whether to show Settings menu item
     case menuSettings = "menuSettings"
     
+    // MARK: - Utility Functions
+    
+    /// Prints all preferences and their values to the console
+    ///
+    /// This function iterates through all preference keys and prints
+    /// their current values from UserDefaults, formatting them according
+    /// to their type.
     func printAllPrefs() {
         let defaults = UserDefaults.standard
+        
+        Logger.preferences.debug("Printing all preference values:")
+        
         for key in PreferenceKeys.allCases {
-            let pref = defaults.object(forKey: key.rawValue) as AnyObject
+            guard let value = defaults.object(forKey: key.rawValue) else {
+                Logger.preferences.debug("\(key.rawValue): Unset")
+                continue
+            }
             
-            switch String(describing: type(of: pref)) {
-            case "__NSCFBoolean" :
-                print("\t" + key.rawValue + ": " + String(describing: ( defaults.bool(forKey: key.rawValue))))
-            case "__NSCFArray" :
-                print("\t" + key.rawValue + ": " + ( String(describing: (defaults.array(forKey: key.rawValue)))))
-            case "__NSTaggedDate":
-                if let object = pref as? Date {
-                    print("\t" + key.rawValue + ": " + object.description(with: Locale.current))
-                } else {
-                    print("\t" + key.rawValue + ": Unknown")
-                }
-            case "__NSCFDictionary":
-                let description = String(describing: defaults.dictionary(forKey: key.rawValue))
-                print("\t" + key.rawValue + ": " + description)
-            case "__NSCFData" :
-                print("\t" + key.rawValue + ": " + (defaults.data(forKey: key.rawValue)?.base64EncodedString() ?? "Unknown"))
-            default :
-                print("\t" + key.rawValue + ": " + ( defaults.object(forKey: key.rawValue) as? String ?? "Unset"))
+            // Format the value based on its type
+            let formattedValue: String
+            
+            switch value {
+            case let boolValue as Bool:
+                formattedValue = String(describing: boolValue)
+                
+            case let arrayValue as [Any]:
+                formattedValue = String(describing: arrayValue)
+                
+            case let dateValue as Date:
+                formattedValue = dateValue.description(with: Locale.current)
+                
+            case let dictValue as [String: Any]:
+                formattedValue = String(describing: dictValue)
+                
+            case let dataValue as Data:
+                formattedValue = dataValue.base64EncodedString()
+                
+            case let stringValue as String:
+                formattedValue = stringValue
+                
+            default:
+                formattedValue = String(describing: value)
             }
+            
+            // Log the key and its value
             if defaults.objectIsForced(forKey: key.rawValue) {
-                print("\t\tForced")
+                Logger.preferences.debug("\(key.rawValue): \(formattedValue) (Forced)")
+            } else {
+                Logger.preferences.debug("\(key.rawValue): \(formattedValue)")
             }
         }
     }
diff --git a/Network Share Mounter/preferences/PreferenceManager.swift b/Network Share Mounter/preferences/PreferenceManager.swift
index d1e565e69f788e7fe791ebab8a720695a469ed07..271c8331b2a0a8d8f8d464044be89cf9b57a384c 100644
--- a/Network Share Mounter/preferences/PreferenceManager.swift	
+++ b/Network Share Mounter/preferences/PreferenceManager.swift	
@@ -9,123 +9,208 @@
 
 import Foundation
 import dogeADAuth
+import OSLog
 
-let kStateDomain = "de.fau.rrze.NetworkShareMounter.doge.state"
-let kSharedDefaultsName = "de.fau.rrze.NetworkShareMounter"
+/// Constants for UserDefaults domains
+private enum UserDefaultsDomains {
+    static let stateDomain = "de.fau.rrze.NetworkShareMounter.doge.state"
+    static let sharedDefaultsName = "de.fau.rrze.NetworkShareMounter"
+}
 
+/// Extension to UserDefaults for dynamic property support
 extension UserDefaults {
     @objc dynamic var Accounts: Data? {
         return data(forKey: Defaults.Accounts)
     }
 }
 
+/// Manages application preferences and user state using UserDefaults
+/// 
+/// This class handles all preference-related operations including:
+/// - Reading and writing user preferences
+/// - Managing AD user information
+/// - Handling state persistence
+/// - Loading default values
 struct PreferenceManager {
+    /// Logger instance for preference operations
+    private static let logger = Logger.preferences
+    
+    /// Standard UserDefaults instance for general preferences
+    private let defaults = UserDefaults.standard
     
-    let defaults = UserDefaults.standard
-    let stateDefaults = UserDefaults.init(suiteName: kStateDomain)
+    /// State-specific UserDefaults instance for user state
+    private let stateDefaults: UserDefaults?
     
+    /// Initializes a new PreferenceManager
+    /// 
+    /// This initializer sets up the UserDefaults instances and loads default values
     init() {
+        stateDefaults = UserDefaults(suiteName: UserDefaultsDomains.stateDomain)
+        
         if let defaultValues = readPropertyList() {
             defaults.register(defaults: defaultValues)
+            Self.logger.debug("Default values loaded successfully")
+        } else {
+            Self.logger.error("Failed to load default values")
         }
     }
     
+    // MARK: - Preference Access Methods
+    
+    /// Retrieves an array for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The array value if found, nil otherwise
     func array(for prefKey: PreferenceKeys) -> [Any]? {
         defaults.array(forKey: prefKey.rawValue)
     }
     
+    /// Retrieves a string for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The string value if found, nil otherwise
     func string(for prefKey: PreferenceKeys) -> String? {
         defaults.string(forKey: prefKey.rawValue)
     }
     
+    /// Retrieves an object for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The object value if found, nil otherwise
     func object(for prefKey: PreferenceKeys) -> Any? {
         defaults.object(forKey: prefKey.rawValue)
     }
     
+    /// Retrieves a dictionary for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The dictionary value if found, nil otherwise
     func dictionary(for prefKey: PreferenceKeys) -> [String:Any]? {
         defaults.dictionary(forKey: prefKey.rawValue)
     }
     
+    /// Retrieves a boolean for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The boolean value
     func bool(for prefKey: PreferenceKeys) -> Bool {
         defaults.bool(forKey: prefKey.rawValue)
     }
     
-    func set(for prefKey: PreferenceKeys, value: Any) {
-        defaults.set(value as AnyObject, forKey: prefKey.rawValue)
+    /// Sets a value for the specified preference key
+    /// - Parameters:
+    ///   - prefKey: The preference key to set
+    ///   - value: The value to set
+    func set<T>(for prefKey: PreferenceKeys, value: T) {
+        defaults.set(value, forKey: prefKey.rawValue)
     }
     
+    /// Retrieves an integer for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The integer value
     func int(for prefKey: PreferenceKeys) -> Int {
         defaults.integer(forKey: prefKey.rawValue)
     }
     
+    /// Retrieves a date for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The date value if found, nil otherwise
     func date(for prefKey: PreferenceKeys) -> Date? {
         defaults.object(forKey: prefKey.rawValue) as? Date
     }
     
+    /// Clears the value for the specified preference key
+    /// - Parameter prefKey: The preference key to clear
     func clear(for prefKey: PreferenceKeys) {
         defaults.set(nil, forKey: prefKey.rawValue)
     }
     
+    /// Retrieves data for the specified preference key
+    /// - Parameter prefKey: The preference key to look up
+    /// - Returns: The data value if found, nil otherwise
     func data(for prefKey: PreferenceKeys) -> Data? {
         defaults.data(forKey: prefKey.rawValue)
     }
     
+    // MARK: - AD User Information Management
+    
+    /// Sets AD user information in UserDefaults
+    /// - Parameter user: The AD user record to store
     func setADUserInfo(user: ADUserRecord) {
+        Self.logger.debug("Setting AD user info for user: \(user.userPrincipal)")
+        
         defaults.set(user.userPrincipal.lowercased(), forKey: PreferenceKeys.lastUser.rawValue)
         
         if let passwordAging = user.passwordAging, passwordAging {
             if let expireDate = user.computedExpireDate {
                 self.set(for: .userPasswordExpireDate, value: expireDate)
+                Self.logger.debug("Password expiration date set: \(expireDate)")
             }
         } else {
             self.clear(for: .userPasswordExpireDate)
+            Self.logger.debug("Password expiration date cleared")
         }
         
-        guard let stateDefaults = stateDefaults else { return }
+        guard let stateDefaults = stateDefaults else {
+            Self.logger.error("Failed to access state defaults")
+            return
+        }
+        
+        // Store user information in state defaults
+        let userInfo: [PreferenceKeys: Any] = [
+            .userCN: user.cn,
+            .userGroups: user.groups,
+            .userPasswordExpireDate: user.computedExpireDate as Any,
+            .userPasswordSetDate: user.passwordSet as Any,
+            .userHome: user.homeDirectory as Any,
+            .userPrincipal: user.userPrincipal,
+            .customLDAPAttributesResults: user.customAttributes as Any,
+            .userShortName: user.shortName,
+            .userUPN: user.upn,
+            .userEmail: user.email as Any,
+            .userFullName: user.fullName,
+            .userFirstName: user.firstName,
+            .userLastName: user.lastName,
+            .userLastChecked: Date()
+        ]
         
-        stateDefaults.set(user.cn, forKey: PreferenceKeys.userCN.rawValue)
-        stateDefaults.set(user.groups, forKey: PreferenceKeys.userGroups.rawValue)
-        stateDefaults.set(user.computedExpireDate, forKey: PreferenceKeys.userPasswordExpireDate.rawValue)
-        stateDefaults.set(user.passwordSet, forKey: PreferenceKeys.userPasswordSetDate.rawValue)
-        stateDefaults.set(user.homeDirectory, forKey: PreferenceKeys.userHome.rawValue)
-        stateDefaults.set(user.userPrincipal, forKey: PreferenceKeys.userPrincipal.rawValue)
-        stateDefaults.set(user.customAttributes, forKey: PreferenceKeys.customLDAPAttributesResults.rawValue)
-        stateDefaults.set(user.shortName, forKey: PreferenceKeys.userShortName.rawValue)
-        stateDefaults.set(user.upn, forKey: PreferenceKeys.userUPN.rawValue)
-        stateDefaults.set(user.email, forKey: PreferenceKeys.userEmail.rawValue)
-        stateDefaults.set(user.fullName, forKey: PreferenceKeys.userFullName.rawValue)
-        stateDefaults.set(user.firstName, forKey: PreferenceKeys.userFirstName.rawValue)
-        stateDefaults.set(user.lastName, forKey: PreferenceKeys.userLastName.rawValue)
-        stateDefaults.set(Date(), forKey: PreferenceKeys.userLastChecked.rawValue)
+        for (key, value) in userInfo {
+            stateDefaults.set(value, forKey: key.rawValue)
+        }
         
-        // Break down the complex expression into simpler steps
+        // Update all users dictionary
         var allUsers = stateDefaults.dictionary(forKey: PreferenceKeys.allUserInformation.rawValue) as? [String: [String: AnyObject]] ?? [:]
         
-        var userInfo = [String: AnyObject]()
-        userInfo["CN"] = user.cn as AnyObject
-        userInfo["groups"] = user.groups as AnyObject
-        userInfo["UserPasswordExpireDate"] = user.computedExpireDate?.description as AnyObject? ?? "" as AnyObject
-        userInfo["UserHome"] = user.homeDirectory as AnyObject? ?? "" as AnyObject
-        userInfo["UserPrincipal"] = user.userPrincipal as AnyObject
-        userInfo["CustomLDAPAttributesResults"] = user.customAttributes?.description as AnyObject? ?? "" as AnyObject
-        userInfo["UserShortName"] = user.shortName as AnyObject
-        userInfo["UserUPN"] = user.upn as AnyObject
-        userInfo["UserEmail"] = user.email as AnyObject? ?? "" as AnyObject
-        userInfo["UserFullName"] = user.fullName as AnyObject
-        userInfo["UserFirstName"] = user.firstName as AnyObject
-        userInfo["UserLastName"] = user.lastName as AnyObject
-        userInfo["UserLastChecked"] = Date() as AnyObject
-
-        allUsers[user.userPrincipal] = userInfo
+        var userInfoDict = [String: AnyObject]()
+        for (key, value) in userInfo {
+            userInfoDict[key.rawValue] = value as AnyObject
+        }
+        
+        allUsers[user.userPrincipal] = userInfoDict
         stateDefaults.setValue(allUsers, forKey: PreferenceKeys.allUserInformation.rawValue)
-    }
-
         
+        Self.logger.debug("Successfully updated user information for: \(user.userPrincipal)")
+    }
+    
+    // MARK: - Private Methods
+    
+    /// Reads the default values from the property list
+    /// - Returns: Dictionary of default values if successful, nil otherwise
     private func readPropertyList() -> [String: Any]? {
-        guard let plistPath = Bundle.main.path(forResource: "DefaultValues", ofType: "plist"),
-              let plistData = FileManager.default.contents(atPath: plistPath) else {
+        guard let plistPath = Bundle.main.path(forResource: "DefaultValues", ofType: "plist") else {
+            Self.logger.error("DefaultValues.plist not found")
+            return nil
+        }
+        
+        guard let plistData = FileManager.default.contents(atPath: plistPath) else {
+            Self.logger.error("Failed to read DefaultValues.plist")
+            return nil
+        }
+        
+        do {
+            let defaults = try PropertyListSerialization.propertyList(from: plistData, format: nil) as? [String: Any]
+            if defaults == nil {
+                Self.logger.error("Failed to parse DefaultValues.plist")
+            }
+            return defaults
+        } catch {
+            Self.logger.error("Error parsing DefaultValues.plist: \(error.localizedDescription)")
             return nil
         }
-        return try? PropertyListSerialization.propertyList(from: plistData, format: nil) as? [String: Any]
     }
 }
diff --git a/Network Share MounterTests/ManagerTests/KeychainManagerMockTests.swift b/Network Share MounterTests/ManagerTests/KeychainManagerMockTests.swift
index a4d93ed8742aad728b9fe6aa08e28cfa6289d429..10ec4e0a4c0442aeb0e7a755561cb41ad34640da 100644
--- a/Network Share MounterTests/ManagerTests/KeychainManagerMockTests.swift	
+++ b/Network Share MounterTests/ManagerTests/KeychainManagerMockTests.swift	
@@ -21,7 +21,7 @@ final class KeychainManagerMockTests: XCTestCase {
             return ["mockKey": "mockValue"]
         }
         
-        override func makeQuery(username: String, service: String = Defaults.keyChainService, accessGroup: String? = nil, label: String? = nil, comment: String? = nil, iCloudSync: Bool? = nil) throws -> [String: Any] {
+        override func makeQuery(username: String, service: String = Defaults.keyChainService, accessGroup: String? = nil, label: String? = nil, comment: String? = nil) throws -> [String: Any] {
             makeQueryCalled = true
             
             if shouldThrowOnMakeQuery {
@@ -72,7 +72,7 @@ final class KeychainManagerMockTests: XCTestCase {
             savedCredentials.removeValue(forKey: key)
         }
         
-        override func removeCredential(forUsername username: String, andService service: String = Defaults.keyChainService, accessGroup: String = Defaults.keyChainAccessGroup, iCloudSync: Bool? = nil) throws {
+        override func removeCredential(forUsername username: String, andService service: String = Defaults.keyChainService, accessGroup: String = Defaults.keyChainAccessGroup) throws {
             let key = "\(service)|\(username)"
             savedCredentials.removeValue(forKey: key)
         }
@@ -148,4 +148,4 @@ final class KeychainManagerMockTests: XCTestCase {
         XCTAssertEqual(try mockKeychainManager.retrievePassword(forShare: testURL1, withUsername: testUsername), testPassword1)
         XCTAssertEqual(try mockKeychainManager.retrievePassword(forShare: testURL2, withUsername: testUsername), testPassword2)
     }
-} 
\ No newline at end of file
+} 
diff --git a/Network Share MounterTests/ManagerTests/KeychainManagerTests.swift b/Network Share MounterTests/ManagerTests/KeychainManagerTests.swift
index 20f4943bf8e88d653af5d2a4269c6ba469f81294..4d9bdf156f41aa5d5ecd4433a5e34c2c1e55096e 100644
--- a/Network Share MounterTests/ManagerTests/KeychainManagerTests.swift	
+++ b/Network Share MounterTests/ManagerTests/KeychainManagerTests.swift	
@@ -141,4 +141,4 @@ class MockKeychainManager: KeychainManager {
         // Simulate the code path where password encoding fails
         throw KeychainError.unexpectedPasswordData
     }
-} 
\ No newline at end of file
+}
diff --git a/Network Share MounterTests/ManagerTests/PreferenceManagerTests.swift b/Network Share MounterTests/ManagerTests/PreferenceManagerTests.swift
new file mode 100644
index 0000000000000000000000000000000000000000..b3a0e6fa94076c3a591762b85c581fc2b0d5ffd2
--- /dev/null
+++ b/Network Share MounterTests/ManagerTests/PreferenceManagerTests.swift	
@@ -0,0 +1,139 @@
+import XCTest
+@testable import Network_Share_Mounter
+
+/// Tests für den PreferenceManager
+/// Fokus auf grundlegende Funktionalität zum Speichern und Abrufen von Einstellungen
+final class PreferenceManagerTests: XCTestCase {
+    
+    // MARK: - Properties
+    
+    var sut: PreferenceManager!
+    let testSuiteName = "de.fau.rrze.NetworkShareMounter.tests"
+    var testDefaults: UserDefaults!
+    
+    // MARK: - Lifecycle
+    
+    override func setUp() {
+        super.setUp()
+        
+        // Test-UserDefaults erstellen und zurücksetzen
+        testDefaults = UserDefaults(suiteName: testSuiteName)
+        testDefaults.removePersistentDomain(forName: testSuiteName)
+        
+        // SUT (System Under Test) initialisieren
+        sut = PreferenceManager()
+    }
+    
+    override func tearDown() {
+        // Aufräumen
+        testDefaults.removePersistentDomain(forName: testSuiteName)
+        testDefaults = nil
+        sut = nil
+        
+        super.tearDown()
+    }
+    
+    // MARK: - Tests: Grundlegende Wertespeicherung und -abruf
+    
+    /// Test: String-Wert speichern und abrufen
+    func testStringValueStorage() {
+        // Given
+        let key = PreferenceKeys.lastUser
+        let value = "testUser"
+        
+        // When
+        sut.set(for: key, value: value)
+        let result = sut.string(for: key)
+        
+        // Then
+        XCTAssertEqual(result, value, "Der gespeicherte String sollte korrekt abgerufen werden")
+    }
+    
+    /// Test: Boolean-Wert speichern und abrufen
+    func testBoolValueStorage() {
+        // Given
+        let key = PreferenceKeys.canQuit
+        let value = true
+        
+        // When
+        sut.set(for: key, value: value)
+        let result = sut.bool(for: key)
+        
+        // Then
+        XCTAssertEqual(result, value, "Der gespeicherte Boolean sollte korrekt abgerufen werden")
+    }
+    
+    /// Test: Integer-Wert speichern und abrufen
+    func testIntValueStorage() {
+        // Given
+        let key = PreferenceKeys.singleUserMode
+        let value = 42
+        
+        // When
+        sut.set(for: key, value: value)
+        let result = sut.int(for: key)
+        
+        // Then
+        XCTAssertEqual(result, value, "Der gespeicherte Integer sollte korrekt abgerufen werden")
+    }
+    
+    /// Test: Array speichern und abrufen
+    func testArrayStorage() {
+        // Given
+        let key = PreferenceKeys.lDAPServerList
+        let value = ["server1.example.com", "server2.example.com"]
+        
+        // When
+        sut.set(for: key, value: value)
+        let result = sut.array(for: key) as? [String]
+        
+        // Then
+        XCTAssertEqual(result, value, "Das gespeicherte Array sollte korrekt abgerufen werden")
+    }
+    
+    /// Test: Dictionary speichern und abrufen
+    func testDictionaryStorage() {
+        // Given
+        let key = PreferenceKeys.allUserInformation
+        let value: [String: Any] = ["name": "Test User", "role": "Admin"]
+        
+        // When
+        sut.set(for: key, value: value)
+        let result = sut.dictionary(for: key)
+        
+        // Then
+        XCTAssertEqual(result?["name"] as? String, "Test User")
+        XCTAssertEqual(result?["role"] as? String, "Admin")
+    }
+    
+    // MARK: - Tests: Werte löschen und Standard-Werte
+    
+    /// Test: Wert löschen
+    func testClearValue() {
+        // Given
+        let key = PreferenceKeys.lastUser
+        sut.set(for: key, value: "testUser")
+        
+        // When
+        sut.clear(for: key)
+        let result = sut.string(for: key)
+        
+        // Then
+        XCTAssertNil(result, "Nach dem Löschen sollte der Wert nil sein")
+    }
+    
+    /// Test: Standard-Werte aus Property List
+    func testDefaultValues() {
+        // Dieser Test setzt voraus, dass es eine Default-Property-List gibt
+        // und dass mindestens ein Wert darin enthalten ist
+        
+        // Ein Beispiel für einen Standard-Wert, der in der Property List definiert sein könnte
+        // Dies ist nur ein Beispiel und muss an die tatsächliche Default-Property-List angepasst werden
+        let key = PreferenceKeys.canQuit
+        let defaultValue = sut.bool(for: key)
+        
+        // Wir überprüfen nicht den genauen Wert, sondern nur dass ein Wert vorhanden ist
+        // Dies dient als Smoke-Test für die Default-Werte-Funktionalität
+        XCTAssertNotNil(defaultValue, "Es sollte ein Default-Wert für \(key) gesetzt sein")
+    }
+} 
\ No newline at end of file
diff --git a/networkShareMounter.xcodeproj/project.pbxproj b/networkShareMounter.xcodeproj/project.pbxproj
index e174b3e96902ba626ded8aff43959db7afd1951d..d7cf5749628c2533da28fe7fdb46d83ebc12e549 100644
--- a/networkShareMounter.xcodeproj/project.pbxproj
+++ b/networkShareMounter.xcodeproj/project.pbxproj
@@ -647,7 +647,7 @@
 				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = C8F68RFW4L;
 				ENABLE_USER_SCRIPT_SANDBOXING = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -677,7 +677,7 @@
 				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = C8F68RFW4L;
 				ENABLE_USER_SCRIPT_SANDBOXING = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -711,7 +711,7 @@
 				"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
 				CODE_SIGN_STYLE = Manual;
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 200;
+				CURRENT_PROJECT_VERSION = 2;
 				DEAD_CODE_STRIPPING = YES;
 				DEVELOPMENT_TEAM = "";
 				"DEVELOPMENT_TEAM[sdk=macosx*]" = C8F68RFW4L;
@@ -761,7 +761,7 @@
 				"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
 				CODE_SIGN_STYLE = Manual;
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 200;
+				CURRENT_PROJECT_VERSION = 2;
 				DEAD_CODE_STRIPPING = YES;
 				DEVELOPMENT_TEAM = "";
 				"DEVELOPMENT_TEAM[sdk=macosx*]" = C8F68RFW4L;