Imports System.IO Imports DigitalData.Modules.Logging ''' ''' Zentrale Klasse für Dokumentenpfad-Verwaltung mit optionalem Laufwerks-Mapping und Temp-Kopie ''' Public Class DocumentPathHandler Private ReadOnly _Logger As Logger Private ReadOnly _LogConfig As LogConfig Private _mappedDrive As String = "" Private _clsmapDrive As Map_Drive Public Sub New(LogConfig As LogConfig) _LogConfig = LogConfig _Logger = LogConfig.GetLogger() _clsmapDrive = New Map_Drive(LogConfig) End Sub Private Function EnsureTempFolder(ByRef tempFolder As String, ByRef errorMessage As String) As Boolean Try _Logger.Debug($"📂 Überprüfe Temp-Ordner: [{tempFolder}]") If String.IsNullOrWhiteSpace(tempFolder) Then _Logger.Debug("⚠️ Temp-Ordner nicht konfiguriert, verwende TEMP_DOCUMENT_FOLDER aus AppSettings") tempFolder = TEMP_DOCUMENT_FOLDER End If ' Fallback, falls global nichts konfiguriert ist If String.IsNullOrWhiteSpace(tempFolder) Then tempFolder = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Digital Data", "taskFLOW", "DocumentViewer", "Temp") _Logger.Info($"⚠️ TEMP_DOCUMENT_FOLDER war leer - verwende Fallback: [{tempFolder}]") TEMP_DOCUMENT_FOLDER = tempFolder End If If Not Directory.Exists(tempFolder) Then Directory.CreateDirectory(tempFolder) _Logger.Info($"📁 Temp-Ordner erstellt: [{tempFolder}]") End If If Not Directory.Exists(tempFolder) Then errorMessage = $"Temp-Ordner konnte nicht erstellt werden: [{tempFolder}]" Return False End If Return True Catch ex As Exception errorMessage = $"Fehler bei Temp-Ordner-Initialisierung: {ex.Message}" _Logger.Error($"❌ {errorMessage}") _Logger.Error(ex) Return False End Try End Function ''' ''' Verarbeitet einen Dokumentenpfad: Optional Mapping, dann Temp-Kopie ''' ''' Quell-Pfad der Datei (UNC oder lokal) ''' Optionen für die Verarbeitung ''' DocumentPathResult mit finalem Pfad und Mapping-Info Public Function ProcessDocumentPath(sourcePath As String, options As DocumentPathOptions) As DocumentPathResult Dim result As New DocumentPathResult With { .SourcePath = sourcePath, .FinalPath = sourcePath, .Success = False, .WasMapped = False, .WasCopiedToTemp = False } Try ' Validierung If String.IsNullOrEmpty(sourcePath) Then result.ErrorMessage = "Quell-Pfad ist leer" _Logger.Error("❌ ProcessDocumentPath: Quell-Pfad ist leer") Return result End If Dim workingPath As String = sourcePath ' ========== SCHRITT 1: OPTIONALES LAUFWERKS-MAPPING ========== If options.EnableMapping AndAlso Not String.IsNullOrEmpty(options.WMSuffix) Then Dim mappingResult = TryMapNetworkDrive(sourcePath, options) If mappingResult.Success Then workingPath = mappingResult.MappedPath _mappedDrive = mappingResult.DriveLetter result.WasMapped = True result.MappedDrive = _mappedDrive _Logger.Info($"✓ Laufwerk gemappt: {_mappedDrive}") Else _Logger.Warn("⚠️ Laufwerks-Mapping fehlgeschlagen - verwende Original-UNC-Pfad") workingPath = sourcePath End If End If ' ========== SCHRITT 2: PRÜFEN OB DATEI EXISTIERT ========== If Not File.Exists(workingPath) Then result.ErrorMessage = $"Datei nicht gefunden: [{workingPath}]" _Logger.Error($"❌ {result.ErrorMessage}") ' Cleanup bei Fehler If result.WasMapped Then UnmapDrive() End If Return result End If ' ========== SCHRITT 3: OPTIONALE TEMP-KOPIE ========== If options.CopyToTemp Then _Logger.Debug($"📂 Starte Temp-Kopie für: [{workingPath}]") Dim tempResult = CopyToTempFolder(workingPath, options.TempFolder) If tempResult.Success Then result.FinalPath = tempResult.TempPath result.WasCopiedToTemp = True result.TempPath = tempResult.TempPath _Logger.Info($"✓ Datei in Temp kopiert: [{Path.GetFileName(tempResult.TempPath)}]") ' Laufwerk unmappen nach erfolgreicher Kopie If result.WasMapped AndAlso options.UnmapAfterCopy Then UnmapDrive() result.WasMapped = False End If Else _Logger.Warn($"⚠️ Temp-Kopie fehlgeschlagen: {tempResult.ErrorMessage}") ' WICHTIG: Nicht den gemappten Pfad behalten, wenn danach ungemappt wird. ' Fallback immer auf stabilen Originalpfad (UNC). result.FinalPath = sourcePath result.WasCopiedToTemp = False result.TempPath = String.Empty If result.WasMapped Then UnmapDrive() result.WasMapped = False End If End If Else result.FinalPath = workingPath _Logger.Debug($"📄 Verwende Pfad ohne Temp-Kopie: [{workingPath}]") End If result.Success = True Return result Catch ex As Exception result.ErrorMessage = $"Unerwarteter Fehler: {ex.Message}" _Logger.Error($"❌ ProcessDocumentPath: {ex.Message}") _Logger.Error(ex) ' Cleanup bei Exception If result.WasMapped Then UnmapDrive() End If Return result End Try End Function ''' ''' Versucht ein Netzlaufwerk zu mappen ''' Private Function TryMapNetworkDrive(sourcePath As String, options As DocumentPathOptions) As MappingResult Dim result As New MappingResult With {.Success = False} Try ' Prüfen ob Pfad mit WMSUFFIX beginnt If Not sourcePath.StartsWith(options.WMSuffix, StringComparison.OrdinalIgnoreCase) Then _Logger.Debug($"📄 Pfad beginnt nicht mit WMSUFFIX - kein Mapping erforderlich") Return result End If _Logger.Debug($"📂 WMSUFFIX erkannt - starte Laufwerks-Mapping") ' Laufwerk mappen Dim mappedDrive As String = "" If Not String.IsNullOrEmpty(options.SpecificDrive) AndAlso options.SpecificDrive.Length = 1 Then ' Spezifisches Laufwerk If _clsmapDrive.MapSpecificDrive(options.SpecificDrive, options.DriveBlacklist, options.WMSuffix) Then mappedDrive = options.SpecificDrive & ":" End If Else ' Automatisches Mapping mappedDrive = _clsmapDrive.MapDriveAutomatic(options.DriveBlacklist, options.WMSuffix) End If If String.IsNullOrEmpty(mappedDrive) Then _Logger.Warn("⚠️ Kein Laufwerk gemappt") Return result End If ' Pfad umschreiben Dim relativePath As String = sourcePath.Substring(options.WMSuffix.Length) If relativePath.StartsWith("\") Then relativePath = relativePath.Substring(1) End If Dim mappedPath As String = mappedDrive.TrimEnd(":"c, "\"c) & ":\" & relativePath _Logger.Debug($"📄 Original: [{sourcePath}]") _Logger.Debug($"📄 Gemappt: [{mappedPath}]") result.Success = True result.DriveLetter = mappedDrive result.MappedPath = mappedPath Return result Catch ex As Exception _Logger.Error($"Fehler beim Mapping: {ex.Message}") _Logger.Error(ex) Return result End Try End Function Private Function CopyToTempFolder(sourcePath As String, tempFolder As String) As TempCopyResult Dim result As New TempCopyResult With {.Success = False} Try Dim configuredTempFolder As String = tempFolder Dim globalTempFolder As String = TEMP_DOCUMENT_FOLDER ' Temp-Ordner validieren/initialisieren (kann tempFolder per ByRef setzen) If Not EnsureTempFolder(tempFolder, result.ErrorMessage) Then _Logger.Warn($"⚠️ {result.ErrorMessage}") _Logger.Warn($"[TempCopy] InputTemp=[{If(String.IsNullOrWhiteSpace(configuredTempFolder), "", configuredTempFolder)}], GlobalTemp=[{If(String.IsNullOrWhiteSpace(globalTempFolder), "", globalTempFolder)}]") Return result End If ' NEU: Effektiven Zielordner immer transparent loggen _Logger.Info($"[TempCopy] Effektiver Temp-Ordner: [{tempFolder}]") _Logger.Debug($"[TempCopy] InputTemp=[{If(String.IsNullOrWhiteSpace(configuredTempFolder), "", configuredTempFolder)}], GlobalTemp=[{If(String.IsNullOrWhiteSpace(globalTempFolder), "", globalTempFolder)}]") ' Eindeutigen Dateinamen generieren Dim originalFileName As String = Path.GetFileName(sourcePath) Dim fileNameWithoutExt As String = Path.GetFileNameWithoutExtension(originalFileName) Dim extension As String = Path.GetExtension(originalFileName) Dim timestamp As String = DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") Dim uniqueFileName As String = $"{fileNameWithoutExt}_{timestamp}{extension}" Dim targetPath As String = Path.Combine(tempFolder, uniqueFileName) _Logger.Debug($"📄 Kopiere nach Temp:") _Logger.Debug($" Von: [{sourcePath}]") _Logger.Debug($" Nach: [{targetPath}]") File.Copy(sourcePath, targetPath, overwrite:=True) result.Success = True result.TempPath = targetPath result.TempFileName = uniqueFileName Return result Catch ex As Exception result.ErrorMessage = $"Fehler beim Kopieren: {ex.Message}" _Logger.Error($"❌ {result.ErrorMessage}") _Logger.Error(ex) Return result End Try End Function ''' ''' Trennt das gemappte Laufwerk ''' Public Sub UnmapDrive() If Not String.IsNullOrEmpty(_mappedDrive) Then Try If _clsmapDrive.DisconnectNetworkDrive(_mappedDrive, force:=True) Then _Logger.Info($"🔌 Laufwerk {_mappedDrive} getrennt") Else _Logger.Warn($"⚠️ Warnung beim Trennen von {_mappedDrive}") End If Catch ex As Exception _Logger.Debug($"Fehler beim Trennen von {_mappedDrive}: {ex.Message}") Finally _mappedDrive = "" End Try End If End Sub ''' ''' Cleanup-Methode (z.B. beim Schließen des Forms) ''' Public Sub Cleanup() UnmapDrive() End Sub #Region "Nested Classes für Optionen und Ergebnisse" ''' ''' Optionen für die Dokumentenpfad-Verarbeitung ''' Public Class DocumentPathOptions ''' Soll Laufwerks-Mapping versucht werden? Public Property EnableMapping As Boolean = False ''' WMSUFFIX für Mapping-Erkennung (z.B. "\\windream\objects") Public Property WMSuffix As String = "" ''' Spezifischer Laufwerksbuchstabe (z.B. "V") oder leer für automatisch Public Property SpecificDrive As String = "" ''' Blacklist für Laufwerksbuchstaben (z.B. "Y,M,V") Public Property DriveBlacklist As String = "" ''' Soll Datei in Temp kopiert werden? Public Property CopyToTemp As Boolean = False ''' Temp-Ordner-Pfad Public Property TempFolder As String = "" ''' Laufwerk nach erfolgreicher Temp-Kopie unmappen? Public Property UnmapAfterCopy As Boolean = True End Class ''' ''' Ergebnis der Dokumentenpfad-Verarbeitung ''' Public Class DocumentPathResult Public Property Success As Boolean Public Property SourcePath As String Public Property FinalPath As String Public Property ErrorMessage As String Public Property WasMapped As Boolean Public Property MappedDrive As String Public Property WasCopiedToTemp As Boolean Public Property TempPath As String End Class Private Class MappingResult Public Property Success As Boolean Public Property DriveLetter As String Public Property MappedPath As String End Class Private Class TempCopyResult Public Property Success As Boolean Public Property TempPath As String Public Property TempFileName As String Public Property ErrorMessage As String End Class #End Region End Class