1. Herfried K. Wagner’s VB.Any
  2. .NET
  3. Code

Dateioperationen

Ermitteln von Laufwerken und deren Typ

Das .NET Framework bietet zwar die Möglichkeit, die logischen Laufwerke zu ermitteln, ein direkter Weg zum Bestimmen des Typs eines Laufwerks fehlt allerdings.

In der WMI findet man eine Antwort auf die Frage, welchen Typ ein Laufwerk hat: Die Klasse Win32_LogicalDisk repräsentiert ein logisches Laufwerk und stellt zahlreiche Informationen darüber bereit. Unter diesen Informationen findet sich auch eine Eigenschaft DriveType, die den Typ angibt. Die im Folgenden angegebene Funktionsprozedur GetDriveType ermittelt über WMI den Typ eines Laufwerks und gibt diesen in Form einer Konstanten aus der Aufzählung DriveType zurück. Damit die oben angegebene Funktionsprozedur funktioniert, muß ein Verweis auf die System.Management.dll existieren und der Namensraum System.Management importiert werden.

Public Enum DriveType
    Unknown = 0
    NoRootDirectory = 1
    RemoveableDisk = 2
    LocalDisk = 3
    NetworkDrive = 4
    CompactDisk = 5
    RamDisk = 6
End Enum

Public Function GetDriveType(ByVal Drive As String) As DriveType
    Drive = "Win32_LogicalDisk='" & Left(Drive, 2) & "'"
    Dim Disk As New ManagementObject(Drive)
    Return _
        DirectCast( _
            [Enum].Parse(GetType(DriveType), Disk("DriveType").ToString()), _
            DriveType _
        )
End Function

Ermitteln des Typs eines Laufwerks.

Die Methode GetLogicalDrives gibt ein Feld von Zeichenfolgen zurück, die die bekannten logischen Laufwerke repräsentieren. Für alle bekannten Laufwerke wird der Typ ermittelt und die Informationen in Form von Meldungen ausgegeben:

For Each Drive As String In Environment.GetLogicalDrives()
    MsgBox( _
        "Drive: " & Drive & ControlChars.NewLine & _
        "Type: " & GetDriveType(Drive).ToString() _
    )
Next Drive

Ausgeben der Typen aller logischen Laufwerke.

Alternativ könnte man den Typ eines Laufwerks über einen PInvoke-Aufruf der Windows-API-Funktion GetDriveType. Ein Beispiel zur Verwendung dieser Funktion findet sich im Artikel „Öffnen und Schliessen eines CD-ROM-Laufwerks ermitteln“.

Ermitteln der Pfade besonderer Ordner

Das .NET Framework stellt zu Ermitteln der Pfade besonderer Ordner die Methode GetFolderPath in der Klasse Environment bereit. Trotz Erweiterung der Auflistung SpecialFolder im .NET Framework 2.0 kann damit nur ein kleiner Teil der Pfade bestimmt werden. Die im Folgenden angegebene Klasse SpecialFolders gibt in ihrer Eigenschaft Folder den Pfad des gewünschten Ordners zurück. Optional kann der Ordner erstellt werden, sollte er noch nicht existieren. Dieses Beispiel ist eine Übersetzung eines Classic Visual Basic-Beispiels „Besondere Ordner“ von Thorsten Dörfler [MVP]:

Imports System.Runtime.InteropServices

Public Class SpecialFolders
    Private Declare Auto Function SHGetFolderPath Lib "shfolder.dll" ( _
        ByVal hwndOwner As IntPtr, _
        ByVal nFolder As Int32, _
        ByVal hToken As IntPtr, _
        ByVal dwFlags As Int32, _
        ByVal pszPath As String _
    ) As Int32

    Private Declare Auto Function SHGetSpecialFolderLocation Lib "shell32.dll" ( _
        ByVal hwndOwner As Int32, _
        ByVal nFolder As Int32, _
        ByRef ppidl As ITEMIDLIST _
    ) As Int32

    Private Declare Auto Function SHGetPathFromIDList Lib "shell32.dll" ( _
        ByVal pidList As Int32, _
        ByVal lpBuffer As String _
    ) As Int32

    Private Declare Auto Function LoadLibrary Lib "kernel32.dll" ( _
        ByVal lpLibFileName As String _
    ) As IntPtr

    Private Declare Auto Function FreeLibrary Lib "kernel32.dll" ( _
        ByVal hLibModule As IntPtr _
    ) As Int32

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure SHITEMID
        Public cb As Int32
        Public abID As Byte
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure ITEMIDLIST
        Public mkid As SHITEMID
    End Structure

    Private Const S_OK As Int32 = 0
    Private Const MAX_PATH As Int32 = 260

    Private Const CSIDL_FLAG_CREATE As Int32 = &H8000

    Public Enum ShellSpecialFolder
        Desktop = &H0
        Programs = &H2
        Personal = &H5
        Favorites = &H6
        Startup = &H7
        Recent = &H8
        SendTo = &H9
        StartMenu = &HB
        MyMusic = &HD
        DesktopDirectory = &H10
        NetHood = &H13
        Fonts = &H14
        Templates = &H15
        CommonStartMenu = &H16
        CommonPrograms = &H17
        CommonStartup = &H18
        CommonDesktopDirectory = &H19
        AppData = &H1A
        PrintHood = &H1B
        LocalAppData = &H1C
        AltStartup = &H1D
        CommonAltStartup = &H1E
        CommonFavorites = &H1F
        InternetCache = &H20
        Cookies = &H21
        History = &H22
        CommonAppData = &H23
        Windows = &H24
        System = &H25
        ProgramFiles = &H26
        MyPictures = &H27
        Profile = &H28
        CommonProgramFiles = &H2B
        CommonTemplates = &H2D
        CommonDocuments = &H2E
        CommonAdminTools = &H2F
        AdminTools = &H30
        CommonMusic = &H35
        CommonPictures = &H36
        CommonVideo = &H37
        Resources = &H38
        ResourcesLocalized = &H39
        CDBurnArea = &H3B
    End Enum

    Public Shared ReadOnly Property Folder( _
        ByVal Folder_ As ShellSpecialFolder, _
        Optional ByVal ForceCreate As Boolean = False _
    ) As String
        Get
            Dim Path As String = New String(" "c, MAX_PATH)
            If ForceCreate Then
                Folder_ = Folder_ Or CSIDL_FLAG_CREATE
            End If
            Dim tIIDL As ITEMIDLIST
            If SHGetSpecialFolderLocation(0, Folder_, tIIDL) = S_OK Then
                If SHGetPathFromIDList(tIIDL.mkid.cb, Path) <> 0 Then
                    Return _
                        Path.Substring( _
                            0, _
                            Path.IndexOf(ControlChars.NullChar) _
                        )
                End If
            Else
                Dim hMod As IntPtr = LoadLibrary("shfolder.dll")
                If Not hMod.Equals(IntPtr.Zero) Then
                    If _
                        SHGetFolderPath( _
                            IntPtr.Zero, _
                            Folder_, _
                            IntPtr.Zero, _
                            0, _
                            Path _
                        ) = S_OK _
                    Then
                        Dim p As Integer = Path.IndexOf(ControlChars.NullChar)
                        If p > -1 Then
                            Return Path.Substring(0, p)
                        Else
                            Return Path
                        End If
                    End If
                    FreeLibrary(hMod)
                End If
            End If
        End Get
    End Property
End Class

Ermitteln der Pfade von Spezialordnern.

Nachstehender Code gibt Namen und Pfade aller bekannten Spezialordner aus:

Dim typ As Type = GetType(SpecialFolders.ShellSpecialFolder)
For Each n As Integer In [Enum].GetValues(typ)
    Me.ListBox1.Items.Add( _
        [Enum].GetName(typ, n) & ":  " & _
        SpecialFolders.Folder(n) _
    )
Next n

Beispiel zur Verwendung der Klasse SpecialFolders.

Erstellen einer sortierten Liste der Dateien in einem Ordner

Mit der Methode Directory.GetFiles bietet das .NET Framework zwar eine Möglichkeit, die Namen der Dateien innerhalb eines Ordners zu ermitteln und nach einer Dateinamenserweiterung zu filtern. Jedoch bietet diese Methode keine Unterstützung für das Sortieren der Dateinamen nach einer Eigenschaft der Dateien. Zu diesem Zweck kann die Methode Array.Sort benutzt werden, der neben dem zu sortierenden Array auch ein Vergleicher, also eine Klasse, welche die Schnittstelle IComparer implementiert, übergeben werden kann, der dazu verwendet wird, die Reihenfolge zweier Dateien zu bestimmen.

Im folgenden Beispiel werden Dateien nach dem Zeitpunkt des letzten Zugriffs sortiert. Dazu wird die Differenz zwischen den Dateizeiten zweier Dateien bestimmt. Da der Rückgabewert der Methode IComparer.Compare den Datentyp Integer besitzt, die Differenz der Dateizeiten jedoch den Datentyp Long, wird das Vorzeichen der Differenz mittels Math.Sign ermittelt und zurückgegeben. Damit das folgende Beispiel funktioniert, muß der Namensraum System.IO importiert werden:

Public Class LastWriteTimeComparer
    Implements IComparer

    Public Function Compare( _
        ByVal x As Object, _
        ByVal y As Object _
    ) As Integer Implements IComparer.Compare
        Return _
            Math.Sign( _
                File.GetLastWriteTime(DirectCast(x, String)).Ticks - _
                File.GetLastWriteTime(DirectCast(y, String)).Ticks _
            )
    End Function
End Class

Die Klasse LastWriteTimeComparer zum Vergleich der Dateizeiten zweier Dateien.

Folgendes Listing enthält ein Beispiel zur Verwendung der vorgestellten Klasse LastWriteTimeComparer. Dabei werden die Namen der Dateien eines Ordners ermittelt und anhand des Datums des letzten Zugriffs sortiert und anschließend in einem ListBox-Steuerelement ausgegeben:

Dim FileNames() As String = Directory.GetFiles("C:\WINDOWS")
Array.Sort(FileNames, New LastWriteTimeComparer())
Me.ListBox1.DataSource = FileNames

Ausgabe der sortierten Dateiliste.