vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#

https://www.vbarchiv.net
Rubrik:    |   VB-Versionen: VB200802.03.09
Erweiterungen für DirectoryInfo/FilesystemInfo

Ein Modul mit Erweiterungen der Klassen DirectoryInfo und FileInfo zur Verwaltung von Atttributen und Zeitangaben im Dateisystem, sowie zum Kopieren und Löschen von Dateien.

Autor:  Manfred BohnBewertung:  Views:  13.850 

Das Modul modIOExtension enthält einige Erweiterungsmethoden für die Klassen 'DirectoryInfo' und 'FileInfo', die im Namespace 'System.IO' enthalten sind.

Eine Instanz der Klasse 'DirectoryInfo' kann auch Angaben zu einer Datei verwalten und eine Instanz der Klasse 'FileInfo' Angaben zu einem Verzeichnis. Die Klasse 'FileSystemInfo' ist die gemeinsame Basisklasse.

Erweiterungsmethoden für die FileSystemInfo-Klasse heften sich an Instanzen der Directory- und der FileInfo-Klasse. Der erste Parameter muss mit dem Attribut 'ByVal' versehen werden.

Bei der Entwicklung eigener Erweiterungen ist zu beachten, dass Instanzen von 'FileSystemInfo' die aktuellen Informationen zum Dateisystem nur bereitstellen, falls zuvor die Methode 'Refresh' aufgerufen worden ist. Bei Erweiterungen, die Änderungen in das Dateisystem eintragen, ist daran zu denken, dass eine Sperre für den Benutzer oder durch ein aktives Anwendungsprogramm gesetzt sein kann (evt. den Code in einen Try-Catch-Block setzen).

Die Funktionen im Modul modIOExtension ermöglichen die Abfrage und Änderung von Attributen und von Zeiteinträgen. Für das Kopieren und Löschen von Dateien sind weitere Ergänzungen enthalten.

Die Subroutine SetAttributes verlangt als zweiten Parameter die Angabe eines Attributs (oder einer bitweisen Kombination [OR] von Attributen) gemäß der FileAttributes-Enumeration. Der dritte Parameter legt fest, ob diese Attribute gesetzt oder gelöscht werden sollen. (Die Methode ist begrenzt auf allgemeingültige Attribute. Spezielle Flags wie 'Compressed', 'Encrypted', 'SparseFile' oder 'Temporär' werden nicht bearbeitet). Bei der Kombination von Attributen im Quellcode muss man ein wenig aufpassen. Intuitiv würde man mit dem 'AND'-Operator arbeiten. Das klappt aber nicht. Bei der Bitweisen Kombination überträgt 'OR' alle gesetzten Bits in die Parametervariable.

Die Funktion AttributeFlag erlaubt die Prüfung, ob ein bestimmtes Atribut (oder eine Kombination von Attributen / OR-Verknüpfung) gesetzt ist. Die Funktion meldet 'False', wenn das Verzeichnis bzw. die Datei nicht vorhanden ist. Es wird keine Ausnahme ausgelöst !! (Falls eine Kombination von Attributen übergeben wird, meldet die Funktion nur dann 'true', wenn ALLE im Parameterwert kombinierten Attribute gesetzt sind.)

Die Funktion AttributeInfo gibt einen Kennstring zurück, der ein Buchstaben-Kürzel für jedes gesetzte Attribut enthält. (Nur relevante Attribute, NORMAL entfällt).

Die Funktion SetTimes trägt einen bestimmten Zeitpunkt ein (für Erstellung und letzte Änderung). Wird im Parameter kein Zeitpunkt angegeben, wird 'Now' eingetragen. Der optionale Parameter LastWriteOnly steuert, ob nur der Eintrag für 'LastWriteTime' angepasst wird. Die Funktion gibt 'false' zurück, falls die Zeitangabe nicht angepasst werden konnte. Beachten Sie, dass Änderungen der Zeiteinträge nur möglich sind, wenn der Schreibzugriff erlaubt ist.

Um festzustellen, wie alt ein Verzeichnis oder eine Datei ist, stehen die Funktionen Days und Minutes zur Verfügung, die das Alter einer Datei (seit Erstellung) in Tagen bzw. Minuten angeben. Days zählt die Tageswechsel. Minutes gibt die Zahl der Minuten seit Erstellung zurück und ist deshalb für die Ermittlung des Alters der aktuell bearbeiteten Dateien geeignet. Falls die Datei oder das Verzeichnis nicht existiert, wird -1 zurückgegeben.

Die Funktion IsModified gibt an, ob ein Verzeichnis oder eine Datei seit der Erstellung modifiziert worden ist. (Die beiden Zeiteinträge werden verglichen.)

Für die Klasse 'DirectoryInfo' ist zusätzlich die Routine SetFileTimes enthalten, die bei allen Dateien im Verzeichnis (ausser System-, versteckte und schreibgeschützte Dateien) den gleichen Zeitpunkt einträgt. Falls ein Eintrag nicht angepasst werden kann, wird das von der Routine ignoriert!

Für die Klasse 'FileInfo' sind drei 'Extensions' enthalten, die direkten Zugriff auf einige besonders nützliche Methoden des 'My.Computer.FileSystem'-Objekts ermöglichen.

Die Erweiterung FileBytes liest den gesamten Dateiinhalt in ein Bytearray. Falls die Funktion scheitert, wird 'Nothing' zurückgegeben.

Die Erweiterung FileCopy erstellt - falls erforderlich - zunächst den fehlenden Teilpfad und kopiert dann die Datei in das Zielverzeichnis. Die Routine meldet im Fall des Scheiterns den Grund in dem Parameter ErrorMessage. Attribute der Quelldatei werden in das Ziel übernommen. Der optionale Parameter AllowOverwrite steuert, ob eine bereits bestehende Zieldatei überschrieben werden darf. Schreibgeschützte Ziel-Dateien werden trotzdem NICHT überschrieben! Der optionale Parameter FixCreationTimeStamp ermöglicht die Übernahme des Erstellungs-Zeiteintrags der Quell-Datei in die kopierte Datei (auch bei bestehendem Schreibschutz).

Die Erweiterung FileDelete ermöglicht als (voreingestellte) Option das Verschieben der Datei in den Papierkorb. Der Parameter DeleteReadOnlyFile steuert, ob auch eine schreibgeschützte Datei gelöscht werden darf. Falls das Löschen scheitert, wird 'false' zurückgegeben und in ErrorMessage steht die Ursache.

Hier einige Aufrufbeispiele:
Das Verzeichnis 'C:\Demo' wird erwartet!!

Public Sub ModIOExtension_Exemp()
  Dim DemoPath As String = "C:\Demo\text.txt"
  Dim fileinfo As New IO.FileInfo(DemoPath)
  If Not fileinfo.Exists Then
    Try
      IO.File.Create(DemoPath)
    Catch
    End Try
  End If
 
  ' Attribut-Kombination setzen
  If Not fileinfo.SetAttributes _
    (IO.FileAttributes.Hidden Or IO.FileAttributes.ReadOnly) Then Stop
 
  ' Gesetzte Attribut-Kombination abfragen
  If Not fileinfo.AttributeFlag _
    (IO.FileAttributes.Hidden Or IO.FileAttributes.ReadOnly) Then Stop
 
  Dim str As String = fileinfo.AttributeInfo
 
  ' Hidden-Attribut löschen
  If Not fileinfo.SetAttributes(IO.FileAttributes.Hidden, False) Then Stop
 
  ' Hidden sollte verschwunden sein
  If fileinfo.AttributeFlag(IO.FileAttributes.Hidden) Then Stop
 
  ' ReadOnly ist noch gesetzt
  If Not fileinfo.AttributeFlag(IO.FileAttributes.ReadOnly) Then Stop
 
  str = fileinfo.AttributeInfo
 
  Dim DestPath As String = "C:\demo\subfolder\nextsubfolder\Kopie.txt"
  Dim nfi As IO.FileInfo
  If Not fileinfo.FileCopy(DestPath, True, NewFileInfo:=nfi, ErrorMessage:=str) Then
    MsgBox(fileinfo.Name & vbCrLf & str, vbExclamation, "FileCopy")
  Else
    If Not nfi.FileDelete(True, FileIO.RecycleOption.DeletePermanently, str) Then
      MsgBox(fileinfo.Name & vbCrLf & str, vbExclamation, "FileDelete")
    End If
  End If
End Sub


Code der Erweiterungsmethoden

Option Strict On
Option Infer Off
Option Explicit On
 
Imports System
Imports Microsoft.VisualBasic 'DateDiff/DateIntervall/FileIO
 
''' <summary>Erweiterungsmethoden für
''' System.IO.DirectoryInfo / System.IO.FileInfo</summary>
Module modIOExtension
 
  ' =========================================================
  ' Extension Methods für die Klasse System.IO.FileSystemInfo
  ' =========================================================
  ''' <summary>Abfrage: Attribut(e) gesetzt?</summary>
  ''' <param name="FileSystemInfo"></param>
  ''' <param name="Attributes">zu prüfende(s) Attribut(e)
  ''' (Attribut-Kombinationen mit OR verknüpfen!)</param>
  <Runtime.CompilerServices.Extension()> _
  Public Function AttributeFlag ( _
    ByVal FileSystemInfo As IO.FileSystemInfo, _
    ByVal Attributes As IO.FileAttributes) As Boolean
 
    With FileSystemInfo
      .Refresh()
      If .Attributes < 0 Then Return False
      Return CBool(.Attributes And Attributes)
    End With
 
  End Function
  ''' <summary>Setzen/Löschen der Attribute eines 
  ''' Filesystem-Items</summary>
  ''' <param name="Attributes">
  ''' Attribute (auch: Kombinationen)</param>
  ''' <param name="Attribute_Value">
  ''' Attribute(e): Setzen (true) oder Löschen (false)</param>
  <Runtime.CompilerServices.Extension()> _
  Public Function SetAttributes( _
    ByVal FileSystemInfo As IO.FileSystemInfo, _
    ByVal Attributes As IO.FileAttributes, _
    Optional ByVal Attribute_Value As Boolean = True) As Boolean
 
    Try
      With FileSystemInfo
        ' Aktualisieren
        .Refresh()
        If Attributes >= IO.FileAttributes.Normal Then
          ' Throw New ArgumentException _
          ' ("Attribut wird nicht unterstützt")
          Return False
        End If
        If Attribute_Value Then
          ' Attribut(e) Setzen 
          .Attributes = .Attributes Or Attributes
          .Refresh()
          ' Überprüfen, ob Attribute gesetzt sind
          Return .AttributeFlag(Attributes)
        Else
          ' Attribut(e) Löschen
          .Attributes = _
          Not ((Not .Attributes) Or Attributes)
          .Refresh()
          ' Überprüfen, ob Attribute gelöscht sind
          Return Not .AttributeFlag(Attributes)
        End If
      End With
    Catch
      Return False
    End Try
 
  End Function
  ''' <summary>Attribut-Information</summary>
  ''' <param name="FileSystemInfo"></param>
  ''' <returns>String-Kennungen der gesetzten Attribute</returns>
  <Runtime.CompilerServices.Extension()> _
  Public Function AttributeInfo ( _
    ByVal FileSystemInfo As IO.FileSystemInfo) As String
 
    Dim str As String = "" ' für Attributkennungen
    Try
      With FileSystemInfo
        .Refresh()
        If .AttributeFlag(IO.FileAttributes.Archive) Then str &= "A"
        If .AttributeFlag(IO.FileAttributes.Compressed) Then str &= "C"
        If .AttributeFlag(IO.FileAttributes.Encrypted) Then str &= "E"
        If .AttributeFlag(IO.FileAttributes.Hidden) Then str &= "H"
        If .AttributeFlag(IO.FileAttributes.ReadOnly) Then str &= "R"
        If .AttributeFlag(IO.FileAttributes.System) Then str &= "S"
        If .AttributeFlag(IO.FileAttributes.Temporary) Then str &= "T"
        If .AttributeFlag(IO.FileAttributes.Offline) Then str &= "O"
      End With
      Return str
    Catch
      Return Nothing
    End Try
 
  End Function
  ''' <summary>Zeitstempel des FileSystem-Items setzen</summary>
  ''' <param name="DirectoryOrFileTime">
  ''' Neue Verzeichnis-Zeit (optional, sonst Now)
  ''' </param>
  ''' <param name="LastWriteOnly">Falls 'true' wird nur 
  ''' der Eintrag 'LastWriteTime' aktualisiert</param>
  <Runtime.CompilerServices.Extension()> _
  Public Function SetTimes ( _
    ByVal FileSystemInfo As IO.FileInfo, _
    Optional ByVal DirectoryOrFileTime As Date = #12:00:00 AM#, _
    Optional ByVal LastWriteOnly As Boolean = False) As Boolean
 
    Try
      ' Zeitangabe bezieht sich auf die lokale Zeitzone!
      With FileSystemInfo
        .Refresh()
        If DirectoryOrFileTime = #12:00:00 AM# Then _
        DirectoryOrFileTime = DateTime.Now
        If Not LastWriteOnly Then
          .CreationTime = DirectoryOrFileTime
        End If
        .Refresh()
        .LastWriteTime = DirectoryOrFileTime
        Return .LastWriteTime = DirectoryOrFileTime
      End With
    Catch ex As Exception
      Return False
    End Try
  End Function
  ''' <summary>Wurde das FileSystem-Item seit seiner 
  ''' Erstellung modifiziert?</summary>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function IsModified ( _
    ByVal FileSystemInfo As IO.FileSystemInfo) As Boolean
 
    With FileSystemInfo
      .Refresh()
      ' Funktion liefert:
      ' 2.Zeitpunkt - 1.Zeitpunkt
      Dim diff As Long = DateDiff(DateInterval.Second, _
        .CreationTimeUtc, .LastWriteTimeUtc)
      If diff < -10 Then
        Throw New Exception ("Inkonsistente Zeiteinträge")
      End If
      Return diff > 59
    End With
 
  End Function
  ''' <summary>Alter des Filesystem-Items (in Tagen)</summary>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function Days ( _
    ByVal FileSystemInfo As IO.FileSystemInfo) As Long
 
    With FileSystemInfo
      .Refresh()
      If Not .Exists Then Return -1
      Return Microsoft.VisualBasic.DateDiff(DateInterval.Day, _
        .CreationTime.Date, DateTime.Today)
    End With
 
  End Function
  ''' <summary>Alter des FileSystem-Items (in Minuten)</summary>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function Minutes ( _
    ByVal FileSystemInfo As IO.FileSystemInfo) As Long
 
    With FileSystemInfo
      .Refresh()
      If Not .Exists Then Return -1
      Return Microsoft.VisualBasic.DateDiff(DateInterval.Minute, _
        .CreationTime, DateTime.Now)
    End With
 
  End Function
  ' =========================================================
  ' Extension Methods für die Klasse System.IO.DirectoryInfo
  ' =========================================================
  ''' <summary>
  ''' Zeitstempel aller Dateien im Verzeichnis setzen</summary>
  ''' <param name="FileTime">
  ''' Neue Datei-Zeit (optional, sonst Now)</param>
  <Runtime.CompilerServices.Extension()> _
  Public Sub SetFileTimes ( _
    ByRef DirectoryInfo As IO.DirectoryInfo, _
    Optional ByVal FileTime As Date = #12:00:00 AM#)
 
    With DirectoryInfo
      If FileTime = #12:00:00 AM# Then FileTime = DateTime.Now
 
      For Each fileinfo As IO.FileInfo In .GetFiles
        ' Alle Files im Verzeichnis (ohne Unterverzeichnisse)
        With fileinfo
          .Refresh()
          If .Exists() Then
            ' versteckte, schreibgeschützte und System-Dateien 
            ' ignorieren
            If Not .AttributeFlag( _
              IO.FileAttributes.Hidden Or _
              IO.FileAttributes.System Or _
              IO.FileAttributes.ReadOnly) Then
 
              Try
                .CreationTime = FileTime
                .LastWriteTime = FileTime
              Catch
                ' wenn nicht, dann eben nicht .... 
              End Try
            End If
          End If
        End With
      Next fileinfo
    End With
  End Sub
  ' =========================================================
  ' Extension Methods für die Klasse System.IO.FileInfo
  ' =========================================================
  ''' <summary>
  ''' Kopieren der Datei (Zielverzeichnis wird ggf. erstellt)
  ''' </summary>
  ''' <param name="DestinationPath">
  ''' Kompletter Pfad der Zeildatei</param>
  ''' <param name="AllowOverwrite">
  ''' Überschreiben im Zielordner erlaubt? (optional)</param>
  ''' <param name="FixCreationTimeStamp">Übernahme der
  ''' Erstellungszeit der Quelldatei in die Zieldatei</param>
  ''' <param name="ErrorMessage">ggf. Fehlermeldung</param>
  ''' <returns>War das Kopieren erfolgreich?</returns>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function FileCopy ( _
    ByVal FileInfo As IO.FileInfo, _
    ByVal DestinationPath As String, _
    Optional ByVal AllowOverwrite As Boolean = False, _
    Optional ByVal FixCreationTimeStamp As Boolean = True, _
    Optional ByRef NewFileInfo As IO.FileInfo = Nothing, _
    Optional ByRef ErrorMessage As String = "") As Boolean
 
    Try
      ' Rückgabe initialisieren
      NewFileInfo = Nothing
      ErrorMessage = ""
 
      With FileInfo
        .Refresh()
        If Not .Exists Then
          ErrorMessage = "Quelle existiert nicht"
          Return False
        End If
 
        Dim SourcePath As String = .FullName.Trim.ToUpper
        DestinationPath = DestinationPath.Trim.ToUpper()
 
        If SourcePath = DestinationPath Then
          ErrorMessage = "Quelle identisch mit Ziel"
          Return False
        End If
 
        If Not AllowOverwrite Then
          If IO.File.Exists(DestinationPath) Then
            ErrorMessage = "Ziel existiert bereits"
            Return False
          End If
        End If
 
        If .AttributeFlag(IO.FileAttributes.Directory) Then
          ErrorMessage = "Die Quelle ist ein Verzeichnis, keine Datei"
          Return False
        End If
 
        Dim destination_info As New IO.FileInfo(DestinationPath)
 
        If .Extension.ToUpper <> destination_info.Extension.ToUpper Then
          ErrorMessage = "Unterschiedliche Datei-Erweiterungen"
          Return False
        End If
 
        With destination_info
          If .AttributeFlag(IO.FileAttributes.Directory) Then
            ErrorMessage = "Das Ziel ist ein Verzeichnis, keine Datei"
            Return False
          End If
 
          ' ggf. fehlenden (Teil-) Pfad erstellen
          My.Computer.FileSystem.CreateDirectory(.Directory.FullName)
        End With
 
        ' Datei in das Zielverzeichnis kopieren
        ' ggf. überschreiben, falls erlaubt
        NewFileInfo = .CopyTo(DestinationPath, AllowOverwrite)
 
        If Not IO.File.Exists(DestinationPath) Then
          ErrorMessage = "Ziel existiert nicht!?"
          NewFileInfo = Nothing
          Return False
        Else
          If FixCreationTimeStamp Then
            If NewFileInfo.IsReadOnly Then
              ' Zeiteintrag ermöglichen
              NewFileInfo.SetAttributes(IO.FileAttributes.ReadOnly, False)
            End If
 
            ' Erstellungszeit in das Ziel übernehmen
            NewFileInfo.CreationTime = FileInfo.CreationTime
 
            If FileInfo.IsReadOnly Then
              ' gelöschtes Attribut erneuern
              NewFileInfo.SetAttributes(IO.FileAttributes.ReadOnly)
            End If
          End If
          Return True
        End If
      End With
    Catch ex As Exception
      ErrorMessage = ex.Message
      Return False
    End Try
 
  End Function
  ''' <summary>Löschen der Datei</summary>
  ''' <param name="Recycle">
  ''' Lösch-Option: Permanent oder Papierkorb</param>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function FileDelete(ByVal FileInfo As IO.FileInfo, _
    Optional ByVal DeleteReadOnlyFile As Boolean = False, _
    Optional ByVal Recycle As FileIO.RecycleOption = _
    FileIO.RecycleOption.SendToRecycleBin, _
    Optional ByRef ErrorMessage As String = "") As Boolean
 
    Try
      ErrorMessage = ""
      With FileInfo
        .Refresh()
        If Not .Exists Then
          ErrorMessage = "Datei existiert nicht"
          Return False
        End If
        If .AttributeFlag(IO.FileAttributes.ReadOnly) Then
          If Not DeleteReadOnlyFile Then
            ErrorMessage = "Datei ist schreibgeschützt"
            Return False
          Else
            ' Schreibschutz darf entfernt werden
            If Not .SetAttributes(IO.FileAttributes.ReadOnly, False) Then
              ErrorMessage = "Schreibschutz kann nicht entfernt werden"
              Return False
            End If
          End If
        End If
        With My.Computer.FileSystem
          .DeleteFile(FileInfo.FullName, _
            FileIO.UIOption.OnlyErrorDialogs, Recycle)
        End With
        .Refresh()
        If .Exists Then
          ErrorMessage = "Datei kann nicht gelöscht werden"
          Return False
        End If
      End With
      Return True
    Catch ex As Exception
      ErrorMessage = ex.Message
      Return False
    End Try
 
  End Function
  ''' <summary>Lesen der Bytes in der Datei</summary>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function FileBytes( _
    ByVal FileInfo As IO.FileInfo) As Byte()
    Try
      With FileInfo
        .Refresh()
        If Not .Exists Then Return Nothing
        Return My.Computer.FileSystem.ReadAllBytes(.FullName)
      End With
    Catch
      Return Nothing
    End Try
 
  End Function
End Module



Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
 
Copyright ©2000-2024 vb@rchiv Dieter OtterAlle Rechte vorbehalten.


Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.