Laufwerke im Listview

  • VB.NET

Es gibt 37 Antworten in diesem Thema. Der letzte Beitrag () ist von Amelie.

    Laufwerke im Listview

    Moin moin

    Ich habe ein Problem mit dem Listview um die Laufwerke in den entsprechenden Gruppen anzeigen zu lassen. Siehe Bildanhang.
    Habe nun schon etliches versucht, komme aber nicht weiter. :(

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub ListDrives()
    2. ' Zuerst die interne Laufwerk-Liste abrufen und dann die externe Laufwerk-Liste
    3. driveManager.ListDrives(CType(2, GetDriveInfo.MediaType)) ' gibt alle internen aus
    4. driveManager.ListDrives(CType(1, GetDriveInfo.MediaType)) ' gibt alle externen aus
    5. End Sub
    6. Private Sub driveManager_DrivesListed(sender As Object, drivesList As List(Of String)) Handles driveManager.DrivesListed
    7. Try
    8. Dim validDrivesInternal As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    9. ' Erstellen und Hinzufügen der Gruppe "Intern" zum ListView
    10. Dim internGroup As New ListViewGroup("internDrives", "Interne Laufwerke")
    11. lvDrives.Groups.Add(internGroup)
    12. ' Hinzufügen der internen Laufwerke zur Gruppe "Intern"
    13. For Each drive As String In validDrivesInternal
    14. Dim item As New ListViewItem(drive)
    15. lvDrives.Items.Add(item).Group = internGroup
    16. Next
    17. Dim validDrivesExternal As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    18. ' Erstellen und Hinzufügen der Gruppe "Extern" zum ListView
    19. Dim externGroup As New ListViewGroup("externDrives", "Externe Laufwerke")
    20. lvDrives.Groups.Add(externGroup)
    21. ' Hinzufügen der externen Laufwerke zur Gruppe "Extern"
    22. For Each drive As String In validDrivesExternal
    23. Dim item As New ListViewItem(drive)
    24. lvDrives.Items.Add(item).Group = externGroup
    25. Next
    26. ' Setze die Auswahl auf das erste Laufwerk, wenn verfügbar
    27. If lvDrives.Items.Count > 0 Then
    28. lvDrives.Items(0).Selected = True
    29. Else
    30. lvDrives.Items.Add("No Drive")
    31. End If
    32. Catch ex As Exception
    33. ' Fehlerbehandlung
    34. 'eventlogger.ExceptionToFile("Fehler: " & ex.Message)
    35. End Try
    36. End Sub

    Bilder
    • listview-1.jpg

      129,29 kB, 768×408, 179 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Was fehlt, ist die Beschreibung, was Du erwartest. Den ist-Zustand sehen wir, aber nicht den Soll-Zustand. Dass das Bild unlogische Sache zeigt, wenn bei intern und extern das gleiche steht, ist klar. Aber wie wäre es denn inhaltlich richtig?
    Und warum gibt es 4 Kategorien, wobei 2 gleich sind? Was ist der Unterschied zwischen "interne Laufwerke" oben und "interne Laufwerke" unten? Genauso "externe Laufwerke".
    Und wo ist der Code dieser driveManager.ListDrives-Methode?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed

    Es sollen die internen und externen Laufwerke in jeweils einer Gruppe im Listview abgebildet werden. Siehe Bildanhang Sollzustand

    Der hier gezeigte Code ist das letzte was ich versuchte. Die Trennung der Drives ist ja richtig, nur bekomme ich die Anzeige im Listview einfach nicht hin.

    Das MainForm
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private WithEvents driveManager As New GetDriveInfo()
    2. Private WithEvents driveCleaner As WriteFiles
    3. Public Sub New()
    4. driveCleaner = New WriteFiles(driveManager)
    5. InitializeComponent()
    6. ListDrives()
    7. End Sub
    8. Private Sub ListDrives()
    9. ' Zuerst die interne Laufwerk-Liste abrufen und dann die externe Laufwerk-Liste
    10. driveManager.ListDrives(CType(2, GetDriveInfo.MediaType))
    11. driveManager.ListDrives(CType(1, GetDriveInfo.MediaType))
    12. End Sub
    13. Private Sub driveManager_DrivesListed(sender As Object, drivesList As List(Of String)) Handles driveManager.DrivesListed
    14. Try
    15. Dim validDrivesInternal As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    16. ' Erstellen und Hinzufügen der Gruppe "Intern" zum ListView
    17. Dim internGroup As New ListViewGroup("internDrives", "Interne Laufwerke")
    18. lvDrives.Groups.Add(internGroup)
    19. ' Hinzufügen der internen Laufwerke zur Gruppe "Intern"
    20. For Each drive As String In validDrivesInternal
    21. Dim item As New ListViewItem(drive)
    22. lvDrives.Items.Add(item).Group = internGroup
    23. Next
    24. Dim validDrivesExternal As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    25. ' Erstellen und Hinzufügen der Gruppe "Extern" zum ListView
    26. Dim externGroup As New ListViewGroup("externDrives", "Externe Laufwerke")
    27. lvDrives.Groups.Add(externGroup)
    28. ' Hinzufügen der externen Laufwerke zur Gruppe "Extern"
    29. For Each drive As String In validDrivesExternal
    30. Dim item As New ListViewItem(drive)
    31. lvDrives.Items.Add(item).Group = externGroup
    32. Next
    33. ' Setze die Auswahl auf das erste Laufwerk, wenn verfügbar
    34. If lvDrives.Items.Count > 0 Then
    35. lvDrives.Items(0).Selected = True
    36. Else
    37. lvDrives.Items.Add("No Drive")
    38. End If
    39. Catch ex As Exception
    40. ' Fehlerbehandlung
    41. 'eventlogger.ExceptionToFile("Fehler: " & ex.Message)
    42. End Try
    43. End Sub



    Die Class:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class GetDriveInfo
    2. Public Event DrivesListed As EventHandler(Of List(Of String))
    3. Public allDrives() As DriveInfo = DriveInfo.GetDrives()
    4. Friend SelectedDrive As DriveInfo
    5. Public Enum MediaType
    6. ExternalOrRemovable = 1
    7. Fixed = 2
    8. End Enum
    9. Private Const ExternalOrRemovableQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='External hard disk media' OR MediaType='Removable media'"
    10. Private Const FixedQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'"
    11. Public Sub ListDrives(driveType As MediaType)
    12. Dim drivesList As New List(Of String)()
    13. Dim query As String = GetQueryByType(driveType)
    14. If query <> "" Then
    15. Dim searcher As New ManagementObjectSearcher(query)
    16. searcher.Options.ReturnImmediately = True
    17. For Each drive As ManagementObject In searcher.Get()
    18. Dim partitionsQuery As String = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{drive("DeviceID")}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
    19. Dim partitionSearcher As New ManagementObjectSearcher(partitionsQuery)
    20. For Each partition As ManagementObject In partitionSearcher.Get()
    21. Dim logicalDisksQuery As String = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partition("DeviceID")}'}} WHERE AssocClass = Win32_LogicalDiskToPartition"
    22. Dim logicalDisksSearcher As New ManagementObjectSearcher(logicalDisksQuery)
    23. For Each logicalDisk As ManagementObject In logicalDisksSearcher.Get()
    24. Dim driveID As String = logicalDisk("DeviceID").ToString() & "\"
    25. ' Prüfe auf Duplikate anhand einer anderen Eigenschaft (hier: DeviceID)
    26. If Not drivesList.Any(Function(d) d.StartsWith(driveID)) Then
    27. drivesList.Add(driveID)
    28. End If
    29. Next
    30. Next
    31. Next
    32. ' Sortiere die Liste der Laufwerksbuchstaben
    33. drivesList.Sort()
    34. RaiseEvent DrivesListed(Me, drivesList)
    35. End If
    36. End Sub
    37. Private Function GetQueryByType(driveType As MediaType) As String
    38. Select Case driveType
    39. Case MediaType.ExternalOrRemovable
    40. Return ExternalOrRemovableQuery
    41. Case MediaType.Fixed
    42. Return FixedQuery
    43. Case Else
    44. Return ""
    45. End Select
    46. End Function

    Bilder
    • listview-2.jpg

      113,97 kB, 768×408, 54 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Der Code ist ja auch moppelt gedoppelt. In driveManager_DrivesListed machen doch Zeile#17-#25 genau das gleiche wie Z#26-34. Kein Wunder, dass es da zu Doppelungen kommt.
    Gegenvorschlag:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private WithEvents driveManager As New GetDriveInfo()
    2. Private WithEvents driveCleaner As WriteFiles
    3. Public Sub New()
    4. driveCleaner = New WriteFiles(driveManager)
    5. InitializeComponent()
    6. ListDrives()
    7. End Sub
    8. Private Sub ListDrives()
    9. ' Zuerst die interne Laufwerk-Liste abrufen und dann die externe Laufwerk-Liste
    10. driveManager.ListDrives(CType(2, GetDriveInfo.MediaType))
    11. driveManager.ListDrives(CType(1, GetDriveInfo.MediaType))
    12. End Sub
    13. Private Sub driveManager_DrivesListed(sender As Object, e As (drivesList As List(Of String), Type As DriveType)) Handles driveManager.DrivesListed
    14. Try
    15. If e.Type = DriveType.Fixed Then
    16. Dim validDrivesInternal As List(Of String) = e.drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    17. ' Erstellen und Hinzufügen der Gruppe "Intern" zum ListView
    18. Dim internGroup As New ListViewGroup("internDrives", "Interne Laufwerke")
    19. lvDrives.Groups.Add(internGroup)
    20. ' Hinzufügen der internen Laufwerke zur Gruppe "Intern"
    21. For Each drive As String In validDrivesInternal
    22. Dim item As New ListViewItem(drive)
    23. lvDrives.Items.Add(item).Group = internGroup
    24. Next
    25. Else
    26. Dim validDrivesExternal As List(Of String) = e.drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    27. ' Erstellen und Hinzufügen der Gruppe "Extern" zum ListView
    28. Dim externGroup As New ListViewGroup("externDrives", "Externe Laufwerke")
    29. lvDrives.Groups.Add(externGroup)
    30. ' Hinzufügen der externen Laufwerke zur Gruppe "Extern"
    31. For Each drive As String In validDrivesExternal
    32. Dim item As New ListViewItem(drive)
    33. lvDrives.Items.Add(item).Group = externGroup
    34. Next
    35. End If
    36. ' Setze die Auswahl auf das erste Laufwerk, wenn verfügbar
    37. If lvDrives.Items.Count > 0 Then
    38. lvDrives.Items(0).Selected = True
    39. Else
    40. lvDrives.Items.Add("No Drive")
    41. End If
    42. Catch ex As Exception
    43. ' Fehlerbehandlung
    44. 'eventlogger.ExceptionToFile("Fehler: " & ex.Message)
    45. End Try
    46. End Sub
    47. End Class
    48. Public Class GetDriveInfo
    49. Public Event DrivesListed As EventHandler(Of (List(Of String), DriveType As DriveType))
    50. Public allDrives() As DriveInfo = DriveInfo.GetDrives()
    51. Friend SelectedDrive As DriveInfo
    52. Public Enum MediaType
    53. ExternalOrRemovable = 1
    54. Fixed = 2
    55. End Enum
    56. Private Const ExternalOrRemovableQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='External hard disk media' OR MediaType='Removable media'"
    57. Private Const FixedQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'"
    58. Public Sub ListDrives(MediaType As MediaType)
    59. Dim drivesList As New List(Of String)()
    60. Dim query As String = GetQueryByType(MediaType)
    61. If query <> "" Then
    62. Dim searcher As New ManagementObjectSearcher(query)
    63. searcher.Options.ReturnImmediately = True
    64. For Each drive As ManagementObject In searcher.Get()
    65. Dim partitionsQuery As String = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{drive("DeviceID")}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
    66. Dim partitionSearcher As New ManagementObjectSearcher(partitionsQuery)
    67. For Each partition As ManagementObject In partitionSearcher.Get()
    68. Dim logicalDisksQuery As String = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partition("DeviceID")}'}} WHERE AssocClass = Win32_LogicalDiskToPartition"
    69. Dim logicalDisksSearcher As New ManagementObjectSearcher(logicalDisksQuery)
    70. For Each logicalDisk As ManagementObject In logicalDisksSearcher.Get()
    71. Dim driveID As String = logicalDisk("DeviceID").ToString() & "\"
    72. ' Prüfe auf Duplikate anhand einer anderen Eigenschaft (hier: DeviceID)
    73. If Not drivesList.Any(Function(d) d.StartsWith(driveID)) Then
    74. drivesList.Add(driveID)
    75. End If
    76. Next
    77. Next
    78. Next
    79. ' Sortiere die Liste der Laufwerksbuchstaben
    80. drivesList.Sort()
    81. RaiseEvent DrivesListed(Me, (drivesList, If(MediaType = MediaType.Fixed, DriveType.Fixed, DriveType.Removable)))
    82. End If
    83. End Sub
    84. Private Function GetQueryByType(driveType As MediaType) As String
    85. Select Case driveType
    86. Case MediaType.ExternalOrRemovable
    87. Return ExternalOrRemovableQuery
    88. Case MediaType.Fixed
    89. Return FixedQuery
    90. Case Else
    91. Return ""
    92. End Select
    93. End Function


    Und hier noch etwas gekürzt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub driveManager_DrivesListed(sender As Object, e As (drivesList As List(Of String), Type As DriveType)) Handles driveManager.DrivesListed
    2. Try
    3. Dim GroupData As (Name As String, Title As String) = If(e.Type = DriveType.Fixed, ("internDrives", "Interne Laufwerke"), ("externDrives", "Externe Laufwerke"))
    4. ' Erstellen und Hinzufügen der Gruppe "Extern" zum ListView
    5. Dim Group As New ListViewGroup(GroupData.Name, GroupData.Title)
    6. lvDrives.Groups.Add(Group)
    7. ' Hinzufügen der externen Laufwerke zur Gruppe "Extern"
    8. For Each drive In e.drivesList.Where(Function(x) Directory.Exists(x))
    9. Dim item As New ListViewItem(drive)
    10. lvDrives.Items.Add(item).Group = Group
    11. Next
    12. ' Setze die Auswahl auf das erste Laufwerk, wenn verfügbar
    13. If lvDrives.Items.Count > 0 Then
    14. lvDrives.Items(0).Selected = True
    15. Else
    16. lvDrives.Items.Add("No Drive")
    17. End If
    18. Catch ex As Exception
    19. ' Fehlerbehandlung
    20. 'eventlogger.ExceptionToFile("Fehler: " & ex.Message)
    21. End Try
    22. End Sub


    btw: Eine Klasse GetDriveInfo zu nennen ist schon ziemlich :S
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    @Amelie Probiere folgende Codes nacheinander aus:

    VB.NET-Quellcode

    1. Private Sub ListDrives()
    2. ' Zuerst die interne Laufwerk-Liste abrufen und dann die externe Laufwerk-Liste
    3. 'driveManager.ListDrives(CType(2, GetDriveInfo.MediaType))
    4. driveManager.ListDrives(CType(1, GetDriveInfo.MediaType))
    5. End Sub

    VB.NET-Quellcode

    1. Private Sub ListDrives()
    2. ' Zuerst die interne Laufwerk-Liste abrufen und dann die externe Laufwerk-Liste
    3. driveManager.ListDrives(CType(2, GetDriveInfo.MediaType))
    4. 'driveManager.ListDrives(CType(1, GetDriveInfo.MediaType))
    5. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Das hatte ich schon alles druch exerziert.

    Ich muss vom Code von @VaporiZed noch etwas ändern dann läuft es glaube ich.
    Ich poste gleich wenn ich es habe.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Das hatte ich schon alles druch exerziert.
    Dann ist Deine Fragestellung / Problembeschreibung völlig daneben:

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany @VaporiZed

    Genau, diese Ausgaben hatte ich auch. Hab dich wohl vorher falsch verstanden.

    Hier nun der Code der funktioniert:

    Spoiler anzeigen

    Auf dem Form:

    VB.NET-Quellcode

    1. Private Sub driveManager_DrivesListed(sender As Object, e As Tuple(Of List(Of String), DriveType)) Handles driveManager.DrivesListed
    2. Try
    3. Dim drivesList As List(Of String) = e.Item1 ' Zugriff auf die Liste der Laufwerke
    4. Dim driveType As DriveType = e.Item2 ' Zugriff auf den Laufwerkstyp
    5. If driveType = DriveType.Fixed Then
    6. Dim validDrivesInternal As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    7. ' Erstellen und Hinzufügen der Gruppe "Intern" zum ListView
    8. Dim internGroup As New ListViewGroup("internDrives", "Interne Laufwerke")
    9. lvDrives.Groups.Add(internGroup)
    10. ' Hinzufügen der internen Laufwerke zur Gruppe "Intern"
    11. For Each drive As String In validDrivesInternal
    12. Dim item As New ListViewItem(drive)
    13. lvDrives.Items.Add(item).Group = internGroup
    14. Next
    15. Else
    16. Dim validDrivesExternal As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    17. ' Erstellen und Hinzufügen der Gruppe "Extern" zum ListView
    18. Dim externGroup As New ListViewGroup("externDrives", "Externe Laufwerke")
    19. lvDrives.Groups.Add(externGroup)
    20. ' Hinzufügen der externen Laufwerke zur Gruppe "Extern"
    21. For Each drive As String In validDrivesExternal
    22. Dim item As New ListViewItem(drive)
    23. lvDrives.Items.Add(item).Group = externGroup
    24. Next
    25. End If
    26. Catch ex As Exception
    27. ' Fehlerbehandlung
    28. ' eventlogger.ExceptionToFile("Fehler: " & ex.Message)
    29. End Try
    30. End Sub


    In der Class:

    VB.NET-Quellcode

    1. Public Class SelectedDrives
    2. Public Event DrivesListed As EventHandler(Of Tuple(Of List(Of String), DriveType))
    3. Public allDrives() As DriveInfo = DriveInfo.GetDrives()
    4. Friend SelectedDrive As DriveInfo
    5. Public Enum MediaType
    6. ExternalOrRemovable = 1
    7. Fixed = 2
    8. End Enum
    9. Private Const ExternalOrRemovableQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='External hard disk media' OR MediaType='Removable media'"
    10. Private Const FixedQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'"
    11. Public Sub ListDrives(MediaType As MediaType)
    12. Dim drivesList As New List(Of String)()
    13. Dim query As String = GetQueryByType(MediaType)
    14. If query <> "" Then
    15. Dim searcher As New ManagementObjectSearcher(query)
    16. searcher.Options.ReturnImmediately = True
    17. For Each drive As ManagementObject In searcher.Get()
    18. Dim partitionsQuery As String = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{drive("DeviceID")}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
    19. Dim partitionSearcher As New ManagementObjectSearcher(partitionsQuery)
    20. For Each partition As ManagementObject In partitionSearcher.Get()
    21. Dim logicalDisksQuery As String = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partition("DeviceID")}'}} WHERE AssocClass = Win32_LogicalDiskToPartition"
    22. Dim logicalDisksSearcher As New ManagementObjectSearcher(logicalDisksQuery)
    23. For Each logicalDisk As ManagementObject In logicalDisksSearcher.Get()
    24. Dim driveID As String = logicalDisk("DeviceID").ToString() & "\"
    25. ' Prüfe auf Duplikate anhand einer anderen Eigenschaft (hier: DeviceID)
    26. If Not drivesList.Any(Function(d) d.StartsWith(driveID)) Then
    27. drivesList.Add(driveID)
    28. End If
    29. Next
    30. Next
    31. Next
    32. ' Sortiere die Liste der Laufwerksbuchstaben
    33. drivesList.Sort()
    34. Dim driveType As DriveType = If(MediaType = MediaType.Fixed, DriveType.Fixed, DriveType.Removable)
    35. RaiseEvent DrivesListed(Me, Tuple.Create(drivesList, driveType))
    36. End If
    37. End Sub
    38. Private Function GetQueryByType(driveType As MediaType) As String
    39. Select Case driveType
    40. Case MediaType.ExternalOrRemovable
    41. Return ExternalOrRemovableQuery
    42. Case MediaType.Fixed
    43. Return FixedQuery
    44. Case Else
    45. Return ""
    46. End Select
    47. End Function

    Bilder
    • listview-3.jpg

      79,78 kB, 756×321, 41 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @Amelie Noch ein kleiner Aufruf-Tipp:

    VB.NET-Quellcode

    1. Private Sub ListDrives()
    2. ' Zuerst die interne Laufwerk-Liste abrufen und dann die externe Laufwerk-Liste
    3. driveManager.ListDrives(SelectedDrives.MediaType.Fixed)
    4. driveManager.ListDrives(SelectedDrives.MediaType.ExternalOrRemovable)
    5. End Sub

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Naja, und - wie geschrieben: Den Code zusammenfassen. Außer den unterschiedlichen Gruppennamen/-bezeichnungen gibt es keinen Codeunterschied. Daher sollte sich der If/Else-Block nur um die Unterschiede kümmern, nicht den gleichen Code duplizieren. Stichwort DRY
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed @RodFromGermany

    Habe die Nacht über noch ein bissel gewerkelt. Wenn alles richtig läuft, schmeiße ich den Try/Catch-Block auch raus.
    Verwende dann:

    VB.NET-Quellcode

    1. AddHandler Application.ThreadException, AddressOf ExceptionHandlerForErrors
    2. AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf ExceptionHandlerForErrors


    Das ganze ist sicher noch zu verbessern ;)

    Spoiler anzeigen

    Auf dem Form:

    VB.NET-Quellcode

    1. Private WithEvents driveManager As New SelectedDrives()
    2. Private WithEvents driveCleaner As WriteFiles
    3. Public Sub New()
    4. driveCleaner = New WriteFiles(driveManager)
    5. 'AddHandler Application.ThreadException, AddressOf ExceptionHandlerForErrors
    6. 'AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf ExceptionHandlerForErrors
    7. InitializeComponent()
    8. ListDrives()
    9. End Sub
    10. Private Sub ListDrives()
    11. ' Zuerst die interne Laufwerk-Liste abrufen und dann die externe Laufwerk-Liste
    12. driveManager.ListDrives(SelectedDrives.MediaType.Fixed)
    13. driveManager.ListDrives(SelectedDrives.MediaType.Removable)
    14. driveManager.ListDrives(SelectedDrives.MediaType.External)
    15. End Sub
    16. Private Sub driveManager_DrivesListed(sender As Object, e As Tuple(Of List(Of String), DriveType)) Handles driveManager.DrivesListed
    17. Try
    18. Dim drivesList As List(Of String) = e.Item1 ' Zugriff auf die Liste der Laufwerke
    19. Dim driveType As DriveType = e.Item2 ' Zugriff auf den Laufwerkstyp
    20. Dim validDrives As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    21. Dim groupName As String = ""
    22. ' Bestimmen des Gruppennamens basierend auf dem Laufwerkstyp
    23. If driveType = DriveType.Fixed Then
    24. groupName = "Interne Festplatten"
    25. ElseIf driveType = DriveType.Removable Then
    26. ' Unterscheidung zwischen USB-Stick und USB-HDD
    27. If validDrives.Any(Function(drive) New DriveInfo(drive).DriveType = DriveType.Removable) Then
    28. groupName = "USB-Stick / SD-Karten"
    29. Else
    30. groupName = "USB-Festplatten"
    31. End If
    32. End If
    33. ' Erstellen und Hinzufügen der entsprechenden Gruppe zum ListView
    34. Dim group As New ListViewGroup($"{groupName}Drives", $"{groupName}")
    35. lvDrives.Groups.Add(group)
    36. ' Hinzufügen der Laufwerke zur entsprechenden Gruppe
    37. For Each drive As String In validDrives
    38. Dim item As New ListViewItem(drive)
    39. lvDrives.Items.Add(item).Group = group
    40. Next
    41. Catch ex As Exception
    42. ' Fehlerbehandlung
    43. ' eventlogger.ExceptionToFile("Fehler: " & ex.Message)
    44. End Try
    45. End Sub


    In der Class:

    VB.NET-Quellcode

    1. Public Class SelectedDrives
    2. Public Event DrivesListed As EventHandler(Of Tuple(Of List(Of String), DriveType))
    3. Public allDrives() As DriveInfo = DriveInfo.GetDrives()
    4. Friend SelectedDrive As DriveInfo
    5. Public Enum MediaType
    6. Fixed = 1
    7. Removable = 2
    8. External = 3
    9. End Enum
    10. Private Function GetQueryByType(driveType As MediaType) As String
    11. Select Case driveType
    12. Case MediaType.Fixed
    13. Return FixedQuery
    14. Case MediaType.Removable
    15. Return RemovableQuery
    16. Case MediaType.External
    17. Return ExternalQuery
    18. Case Else
    19. Return ""
    20. End Select
    21. End Function
    22. Private Const RemovableQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='External hard disk media'"
    23. Private Const ExternalQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Removable media'"
    24. Private Const FixedQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'"
    25. Public Sub ListDrives(MediaType As MediaType)
    26. Dim drivesList As New List(Of String)()
    27. Dim query As String = GetQueryByType(MediaType)
    28. If query <> "" Then
    29. Dim searcher As New ManagementObjectSearcher(query)
    30. searcher.Options.ReturnImmediately = True
    31. For Each drive As ManagementObject In searcher.Get()
    32. Dim partitionsQuery As String = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{drive("DeviceID")}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
    33. Dim partitionSearcher As New ManagementObjectSearcher(partitionsQuery)
    34. For Each partition As ManagementObject In partitionSearcher.Get()
    35. Dim logicalDisksQuery As String = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partition("DeviceID")}'}} WHERE AssocClass = Win32_LogicalDiskToPartition"
    36. Dim logicalDisksSearcher As New ManagementObjectSearcher(logicalDisksQuery)
    37. For Each logicalDisk As ManagementObject In logicalDisksSearcher.Get()
    38. Dim driveID As String = logicalDisk("DeviceID").ToString() & "\"
    39. ' Prüfe auf Duplikate anhand einer anderen Eigenschaft (hier: DeviceID)
    40. If Not drivesList.Any(Function(d) d.StartsWith(driveID)) Then
    41. drivesList.Add(driveID)
    42. End If
    43. Next
    44. Next
    45. Next
    46. ' Sortiere die Liste der Laufwerksbuchstaben
    47. drivesList.Sort()
    48. Dim driveType As DriveType = If(MediaType = MediaType.Fixed, DriveType.Fixed, DriveType.Removable)
    49. RaiseEvent DrivesListed(Me, Tuple.Create(drivesList, driveType))
    50. End If
    51. End Sub


    Verbesserungen:

    VB.NET-Quellcode

    1. Public Enum MediaType
    2. Fixed = 1
    3. External = 2
    4. Removable = 3
    5. End Enum
    6. Private Function GetQueryByType(driveType As MediaType) As String
    7. Select Case driveType
    8. Case MediaType.Fixed
    9. Return FixedQuery
    10. Case MediaType.External
    11. Return ExternalQuery
    12. Case MediaType.Removable
    13. Return RemovableQuery
    14. Case Else
    15. Return ""
    16. End Select
    17. End Function
    18. Private Const ExternalQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='External hard disk media'"
    19. Private Const RemovableQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Removable media'"
    20. Private Const FixedQuery As String = "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'"






    EDIT : 10:30 Uhr
    ----------------------

    Baue das Form gerade um. Auslagern in eine Class!
    Bilder
    • Listview4.jpg

      87,11 kB, 756×321, 257 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Amelie“ ()

    Amelie schrieb:

    Wenn alles richtig läuft, schmeiße ich den Try/Catch-Block auch raus.
    Du solltest gar nicht mit Try/Catch arbeiten und wenn, dann nur mit expliziten Exceptions.
    Mit nem leeren Catch-Block in der Entwicklungsphase verschleierst Du doch die Ursachen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @VaporiZed @RodFromGermany

    So habe es geschafft. :)
    Die Try/Catch sind weg. Soweit alles in separate Klassen gebracht und noch die Trennung von USB-Festplatten und anderen USB-Datenträgern.
    Ideen etc um es ggf noch mehr an OOP und DRY etc. anzupassen lese ich gerne.


    Das Form: EDIT 21:15 Funktion verschoben
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class frmMain
    2. Private WithEvents eventlogger As New Eventloger()
    3. Private WithEvents driveManager As New DriveManager()
    4. Private WithEvents driveProperty As New DriveProperty()
    5. Public Sub New()
    6. AddHandler Application.ThreadException, AddressOf ExceptionHandlerForErrors
    7. AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf ExceptionHandlerForErrors
    8. InitializeComponent()
    9. ListDrives()
    10. End Sub
    11. ' Fehlerbehandlungen
    12. Private Sub ExceptionHandlerForErrors(sender As Object, e As System.Threading.ThreadExceptionEventArgs)
    13. ShowError(e.Exception)
    14. End Sub
    15. Private Sub ExceptionHandlerForErrors(sender As Object, e As System.UnhandledExceptionEventArgs)
    16. ShowError(DirectCast(e.ExceptionObject, Exception))
    17. End Sub
    18. Private Sub ShowError(ex As Exception)
    19. Dim newMessage As String = "Eine Fehlermeldung wurde im LogFile eingetragen!" & Environment.NewLine & ex.Message
    20. eventlogger.ExceptionToFile(newMessage)
    21. End Sub
    22. ' Methode zum Aufrufen der Laufwerkliste
    23. Private Sub ListDrives()
    24. driveManager.ListDrives(DriveManager.MediaType.Fixed) ' Liste der internen Festplatten aufrufen
    25. driveManager.ListDrives(DriveManager.MediaType.External) ' Liste der externen Festplatten aufrufen
    26. driveManager.ListDrives(DriveManager.MediaType.Removable) ' Liste der wechselbaren Laufwerke aufrufen
    27. End Sub
    28. ' Ereignishandler für das "DrivesListed" Ereignis des DriveManagers
    29. Private Sub driveManager_DrivesListed(sender As Object, e As Tuple(Of List(Of String), DriveType)) Handles driveManager.DrivesListed
    30. ' Liste der zurückgegebenen Laufwerke
    31. Dim drivesList As List(Of String) = e.Item1
    32. ' Typ des zurückgegebenen Laufwerks
    33. Dim driveType As DriveType = e.Item2
    34. ' Liste gültiger Laufwerke
    35. Dim validDrives As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    36. ' Ermitteln des Gruppennamens basierend auf dem Laufwerkstyp
    37. Dim groupName As String = GetDriveGroupName(driveType, validDrives)
    38. ' Hinzufügen einer neuen ListView-Gruppe mit dem ermittelten Gruppennamen
    39. Dim group As New ListViewGroup($"{groupName}Drives", $"{groupName}")
    40. lvDrives.Groups.Add(group)
    41. ' Hinzufügen der Laufwerke zur entsprechenden Gruppe in der ListView
    42. For Each drive As String In drivesList
    43. Dim item As New ListViewItem(drive)
    44. lvDrives.Items.Add(item).Group = group
    45. Next
    46. End Sub
    47. ' EDIT 21:15
    48. ' Die Funktion ist nun auch in der Class !!
    49. '--------------------------------------------------
    50. ' Funktion zur Bestimmung des Gruppennamens basierend auf dem Laufwerkstyp
    51. Private Function GetDriveGroupName(driveType As DriveType, validDrives As List(Of String)) As String
    52. If driveType = DriveType.Fixed Then
    53. ' Gruppenname für interne Festplatten
    54. Return "Interne Festplatten"
    55. ElseIf driveType = DriveType.Removable Then
    56. ' Unterscheidung zwischen USB-Stick / SD-Karten und USB-Festplatten
    57. If validDrives.Any(Function(drive) New DriveInfo(drive).DriveType = DriveType.Removable) Then
    58. ' Gruppenname für USB-Stick oder SD-Karten
    59. Return "USB-Stick / SD-Karten"
    60. Else
    61. ' Gruppenname für USB-Festplatten
    62. Return "USB-Festplatten"
    63. End If
    64. Else
    65. ' Rückgabe eines Standardwerts
    66. Return ""
    67. End If
    68. End Function
    69. ' --------------------------------------------------
    70. ' Methode ein Laufwerk zu setzen
    71. Private Sub lvDrives_ItemSelectionChanged(sender As Object, e As ListViewItemSelectionChangedEventArgs) Handles lvDrives.ItemSelectionChanged
    72. If e.IsSelected Then
    73. For Each item As ListViewItem In lvDrives.Items
    74. If item IsNot e.Item Then
    75. ' Alle anderen Elemente abwählen
    76. item.Selected = False
    77. End If
    78. Next
    79. ' Setze das ausgewählte Laufwerk im driveManager
    80. driveManager.SelectedDrive = New DriveInfo(e.Item.Text)
    81. ' Zeige alle Laufwerkinfos
    82. UpdateDriveInfos()
    83. ' Aktualisiere das Label mit dem ausgewählten Laufwerk
    84. UpdateSelectedDriveLabel()
    85. ' Zeige eine MessageBox, wenn das Laufwerk C:\ ausgewählt wurde
    86. ShowSelectedDriveMessageBox(e.Item.Text)
    87. End If
    88. End Sub
    89. ' Methode zur Aktualisierung der Listbox mit Laufwerk Infos
    90. Private Sub UpdateDriveInfos()
    91. driveProperty.ListDriveInfo(CChar(driveManager.SelectedDrive.Name), lbDriveInfos)
    92. End Sub
    93. ' Methode zur Aktualisierung des Labels mit dem ausgewählten Laufwerk
    94. Private Sub UpdateSelectedDriveLabel()
    95. lblSelectedDrive.Text = "Ausgewähltes Laufwerk: " & driveManager.SelectedDrive.Name
    96. End Sub
    97. ' Methode zum Anzeigen einer MessageBox, wenn das Laufwerk C:\ ausgewählt wurde
    98. Private Sub ShowSelectedDriveMessageBox(selectedDrive As String)
    99. If selectedDrive.ToUpper() = "C:\" Then
    100. MessageBox.Show("Sie haben das Laufwerk C:\ ausgewählt.", "Ausgewähltes Laufwerk", MessageBoxButtons.OK, MessageBoxIcon.Information)
    101. End If
    102. End Sub
    103. End Class



    Eine Class:1
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class DriveManager
    2. ' Event, das ausgelöst wird, wenn die Laufwerke aufgelistet sind
    3. Public Event DrivesListed As EventHandler(Of Tuple(Of List(Of String), DriveType))
    4. ' Array, das alle Laufwerksinformationen speichert
    5. Public allDrivesInfos() As DriveInfo = DriveInfo.GetDrives()
    6. ' Das ausgewählte Laufwerk
    7. Public SelectedDrive As DriveInfo
    8. ' Enumeration für die verschiedenen Arten von Laufwerken
    9. Public Enum MediaType
    10. Fixed = 1 ' Interne HDDs
    11. External = 2 ' Externe HDDs
    12. Removable = 3 ' USB-Sticks / SD-Karten
    13. End Enum
    14. ' Funktion, die eine WMI-Abfrage je nach Laufwerkstyp zurückgibt
    15. Private Function GetWMIQuery(driveType As MediaType) As String
    16. Select Case driveType
    17. Case MediaType.Fixed
    18. Return "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'"
    19. Case MediaType.External
    20. Return "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='External hard disk media'"
    21. Case MediaType.Removable
    22. Return "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Removable media'"
    23. Case Else
    24. Return "" ' Leerer String für den Fall, dass kein gültiger Typ angegeben wurde
    25. End Select
    26. End Function
    27. ' Methode zum Auflisten der Laufwerke basierend auf dem angegebenen Typ
    28. Public Sub ListDrives(MediaType As MediaType)
    29. ' Liste, um die gefundenen Laufwerke zu speichern
    30. Dim drivesList As New List(Of String)()
    31. ' Abrufen der WMI-Abfrage für den angegebenen Laufwerkstyp
    32. Dim query As String = GetWMIQuery(MediaType)
    33. ' Prüfen, ob die Abfrage gültig ist
    34. If query <> "" Then
    35. ' Durchführen der WMI-Abfrage
    36. Dim searcher As New ManagementObjectSearcher(query)
    37. searcher.Options.ReturnImmediately = True
    38. ' Durchlaufen der Ergebnisse der WMI-Abfrage
    39. For Each drive As ManagementObject In searcher.Get()
    40. Dim partitionsQuery As String = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{drive("DeviceID")}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
    41. Dim partitionSearcher As New ManagementObjectSearcher(partitionsQuery)
    42. ' Durchlaufen der Partitionen für jedes gefundene Laufwerk
    43. For Each partition As ManagementObject In partitionSearcher.Get()
    44. Dim logicalDisksQuery As String = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partition("DeviceID")}'}} WHERE AssocClass = Win32_LogicalDiskToPartition"
    45. Dim logicalDisksSearcher As New ManagementObjectSearcher(logicalDisksQuery)
    46. ' Durchlaufen der logischen Laufwerke für jede gefundene Partition
    47. For Each logicalDisk As ManagementObject In logicalDisksSearcher.Get()
    48. Dim driveID As String = logicalDisk("DeviceID").ToString() & "\"
    49. ' Hinzufügen des Laufwerks, wenn es nicht bereits in der Liste vorhanden ist
    50. If Not drivesList.Any(Function(d) d.StartsWith(driveID)) Then
    51. drivesList.Add(driveID)
    52. End If
    53. Next
    54. Next
    55. Next
    56. ' Sortieren der Laufwerksliste
    57. drivesList.Sort()
    58. ' Bestimmen des Laufwerkstyps
    59. Dim driveType As DriveType = If(MediaType = MediaType.Fixed, DriveType.Fixed, DriveType.Removable)
    60. ' Auslösen des Events und Übergeben der Liste und des Laufwerkstyps
    61. RaiseEvent DrivesListed(Me, Tuple.Create(drivesList, driveType))
    62. ' Erstellen einer lesbaren Zeichenfolge für die Laufwerke
    63. Dim drivesString As String = String.Join(" ", drivesList)
    64. ' Anzeige der Laufwerksliste und des Laufwerkstyps in der Debug-Ausgabe
    65. Debug.WriteLine($"Laufwerke: {drivesString}, Laufwerkstyp: {driveType}")
    66. End If
    67. End Sub
    68. Public Function GetDriveInfo(driveLetter As Char) As DriveInfo
    69. ' Gibt die DriveInfo für das angegebene Laufwerk zurück
    70. Return allDrivesInfos.FirstOrDefault(Function(d) d.Name.StartsWith(driveLetter))
    71. End Function
    72. End Class



    Eine Class:2
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class DriveProperty
    2. Private ReadOnly driveManager As New DriveManager()
    3. Public drive As DriveInfo ' Instanzvariable für DriveInfo
    4. ' Funktion zur Abrufung des Laufwerks basierend auf dem Laufwerksbuchstaben
    5. Public Sub SetDriveInfo(driveLetter As Char)
    6. drive = driveManager.GetDriveInfo(driveLetter)
    7. End Sub
    8. ' Funktion zur Überprüfung, ob das Laufwerk bereit ist
    9. Public Function DriveIsReady(driveLetter As Char) As Boolean
    10. Dim drivePath As String = $"{driveLetter}:\\"
    11. Return Directory.Exists(drivePath)
    12. End Function
    13. ' Methode zur gemeinsamen Überprüfung und Rückgabe von Laufwerksinformationen
    14. Private Function GetDriveInfoAndCheck(driveLetter As Char) As DriveInfo
    15. If Not DriveIsReady(driveLetter) Then
    16. Return Nothing
    17. End If
    18. SetDriveInfo(driveLetter)
    19. Return drive
    20. End Function
    21. ' Methode zur Speicherplatzgewinnung
    22. Public Function GetTotalSpace(driveLetter As Char) As Long
    23. Dim drive As DriveInfo = GetDriveInfoAndCheck(driveLetter)
    24. If drive IsNot Nothing Then
    25. Return drive.TotalSize
    26. End If
    27. Return -1
    28. End Function
    29. ' Methode zur Speicherplatzgewinnung
    30. Public Function GetFreeSpace(driveLetter As Char) As Long
    31. Dim drive As DriveInfo = GetDriveInfoAndCheck(driveLetter)
    32. If drive IsNot Nothing Then
    33. Return drive.AvailableFreeSpace
    34. End If
    35. Return -1
    36. End Function
    37. ' Methode zum Dateisystem auslesen
    38. Public Function GetFileSystem(driveLetter As Char) As String
    39. Dim drive As DriveInfo = GetDriveInfoAndCheck(driveLetter)
    40. If drive IsNot Nothing Then
    41. Return drive.DriveFormat
    42. End If
    43. Return "N/A"
    44. End Function
    45. ' Methode um die Infos zur Listbox
    46. Public Sub ListDriveInfo(driveLetter As Char, listBox As ListBox)
    47. If Not DriveIsReady(driveLetter) Then
    48. listBox.Items.Clear()
    49. listBox.Items.Add($" Laufwerk {driveLetter}: Informationen nicht verfügbar.")
    50. Return ' Verlasse die Methode, wenn das Laufwerk nicht bereit ist
    51. End If
    52. Dim driveInfo As DriveInfo = GetDriveInfoAndCheck(driveLetter)
    53. If driveInfo IsNot Nothing Then
    54. listBox.Items.Clear()
    55. listBox.Items.Add($" Laufwerk: {driveLetter}:\")
    56. listBox.Items.Add($" Dateisystem: {driveInfo.DriveFormat}")
    57. listBox.Items.Add($" Gesamter Speicherplatz: {FormatSpace(driveInfo.TotalSize)}")
    58. listBox.Items.Add($" Freier Speicherplatz: {FormatSpace(driveInfo.AvailableFreeSpace)}")
    59. End If
    60. End Sub
    61. ' Methode zur Speicherplatz-Formatierung
    62. Private Function FormatSpace(space As Long) As String
    63. Dim units() As String = {"Bytes", "KB", "MB", "GB", "TB"}
    64. Dim index As Integer = 0
    65. Dim size As Double = space
    66. While size >= 1024 AndAlso index < units.Length - 1
    67. size /= 1024
    68. index += 1
    69. End While
    70. Return $"{size:N2} {units(index)}"
    71. End Function
    72. End Class

    Bilder
    • Listview5.jpg

      220,75 kB, 1.071×483, 96 mal angesehen
    • Listview5.jpg

      180,01 kB, 831×540, 88 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Amelie“ ()

    @VaporiZed @RodFromGermany @ErfinderDesRades @siycah

    Habe nun mal alles versucht im Sinne von OOP, CleanCode usw.. umzubauen.

    Verwendet habe ich nun ein Treeview für die Laufwerke ( Gruppen der Laufwerke ) und je mal eine ListBox / Listview für die Laufwerks Informationen.
    Das ganze klappt auch mit dem USB-Monitor, den ich aber hier mal weggelassen habe.

    Hier nun mein Code. Bin über weiter Vorschläge offen.

    Das Mainform
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class frmMain
    2. ' Eigenschaft zum Zugriff auf die DriveManager-Instanz
    3. Public ReadOnly Property DriveManagerInstance As DriveManager
    4. ' Instanz des DriveManagers
    5. Public WithEvents driveManager As New DriveManager()
    6. ' Instanz des TreeManagers
    7. Public WithEvents treeManager As TreeManager
    8. Public Sub New()
    9. ' Fehlerbehandlung für den Anwendungs-Thread und die App-Domäne einrichten
    10. AddHandler Application.ThreadException, AddressOf ExceptionHandlerForErrors
    11. AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf ExceptionHandlerForErrors
    12. ' Initialisierung des Formulars
    13. InitializeComponent()
    14. ' Übergeben des tvDrives Controls bei der Erstellung der TreeManager-Instanz
    15. treeManager = New TreeManager(driveManager, tvDrives)
    16. ' Auflisten der Laufwerke im TreeView
    17. treeManager.ListDrives()
    18. ' Anzeigen der Laufwerksinformationen in ListBox und ListView
    19. ShowDriveinfosListBox(driveManager.SelectedDrive)
    20. ShowDriveinfosListView(driveManager.SelectedDrive)
    21. End Sub
    22. ' Methoden für die Fehlerbehandlung
    23. #Region "Fehlerbehandlungen"
    24. ' Behandlung von Fehlern im Anwendungsthread
    25. Private Sub ExceptionHandlerForErrors(sender As Object, e As System.Threading.ThreadExceptionEventArgs)
    26. ShowError(e.Exception)
    27. End Sub
    28. ' Behandlung von unbehandelten Ausnahmen
    29. Private Sub ExceptionHandlerForErrors(sender As Object, e As System.UnhandledExceptionEventArgs)
    30. ShowError(DirectCast(e.ExceptionObject, Exception))
    31. End Sub
    32. ' Anzeige von Fehlern in einer MessageBox und Debug-Ausgabe
    33. Private Sub ShowError(ex As Exception)
    34. Dim newMessage As String = $"Ein Fehler wurde registriert!{ Environment.NewLine} {ex.Message} { Environment.NewLine} {ex.StackTrace}"
    35. MessageBox.Show(newMessage, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
    36. Debug.WriteLine(newMessage)
    37. End Sub
    38. #End Region
    39. #Region "LaufwerksInfos anzeigen"
    40. ' Event-Handler zum Anzeigen der Laufwerksinformationen
    41. Private Sub HandleShowDriveInfosEvent(driveInfos As DriveInfo) Handles treeManager.ShowDriveInfos
    42. ' Anzeige der Laufwerksinformationen in ListBox und ListView
    43. ShowDriveinfosListBox(driveManager.SelectedDrive)
    44. ShowDriveinfosListView(driveManager.SelectedDrive)
    45. End Sub
    46. ' Methode zur Aktualisierung der Listbox mit Laufwerkinformationen
    47. #Region "Listbox"
    48. Private Sub ShowDriveinfosListBox(driveInfo As DriveInfo)
    49. ' ListBox leeren
    50. listBoxDriveInfo.Items.Clear()
    51. If driveInfo Is Nothing Then
    52. ' Anzeige einer Meldung, wenn kein Laufwerk ausgewählt ist
    53. listBoxDriveInfo.Items.Add("Kein Laufwerk ausgewählt")
    54. Else
    55. ' Laufwerksbuchstabe
    56. Dim driveLetterWithoutBackslash = driveInfo.Name.TrimEnd("\"c)
    57. listBoxDriveInfo.Items.Add($"Laufwerksbuchstabe: ({driveLetterWithoutBackslash})")
    58. listBoxDriveInfo.Items.Add($"Buchstabe & Name: ({driveInfo.Name}) {driveInfo.VolumeLabel}")
    59. ' Dateisystem
    60. listBoxDriveInfo.Items.Add($"Dateisystem: {driveInfo.DriveFormat}")
    61. ' Gesamtspeicherplatz
    62. listBoxDriveInfo.Items.Add($"Gesamtspeicherplatz: {driveManager.FormatSpace(driveInfo.TotalSize)}")
    63. ' Freier Speicherplatz
    64. listBoxDriveInfo.Items.Add($"Freier Speicherplatz: {driveManager.FormatSpace(driveInfo.TotalFreeSpace)}")
    65. End If
    66. End Sub
    67. #End Region
    68. ' Methode zur Aktualisierung der ListView mit Laufwerkinformationen
    69. #Region "Listview"
    70. Private Sub ShowDriveinfosListView(driveInfo As DriveInfo)
    71. listViewDriveInfo.Clear() ' Vorbereitung der ListView
    72. ' Konfiguration der Spalten für die ListView
    73. listViewDriveInfo.View = View.Details
    74. listViewDriveInfo.Columns.Add("Eigenschaft", 180)
    75. listViewDriveInfo.Columns.Add("Wert", 90)
    76. If driveInfo Is Nothing Then
    77. ' Anzeige einer Meldung, wenn kein Laufwerk ausgewählt ist
    78. AddListViewItem("Kein Laufwerk ausgewählt", "")
    79. Else
    80. ' Laufwerksinformationen hinzufügen
    81. Dim driveLetterWithoutBackslash = driveInfo.Name.TrimEnd("\"c)
    82. AddListViewItem("Laufwerksbuchstabe", $"({driveLetterWithoutBackslash})")
    83. AddListViewItem("Buchstabe & Name", $"({driveInfo.Name}) {driveInfo.VolumeLabel}")
    84. AddListViewItem("Dateisystem", driveInfo.DriveFormat)
    85. AddListViewItem("Gesamtspeicherplatz", driveManager.FormatSpace(driveInfo.TotalSize))
    86. AddListViewItem("Freier Speicherplatz", driveManager.FormatSpace(driveInfo.TotalFreeSpace))
    87. End If
    88. End Sub
    89. Private Sub AddListViewItem(PropertyText As String, ValueText As String)
    90. Dim listViewItem As New ListViewItem(PropertyText)
    91. listViewItem.SubItems.Add(ValueText)
    92. listViewDriveInfo.Items.Add(listViewItem)
    93. End Sub
    94. ' Methode zum Verhindern der Spaltenbreitenänderung in der ListView
    95. Private Sub listViewDriveInfo_ColumnWidthChanging(sender As Object, e As System.Windows.Forms.ColumnWidthChangingEventArgs) Handles listViewDriveInfo.ColumnWidthChanging
    96. Dim LstVw As ListView = CType(sender, ListView)
    97. Select Case e.ColumnIndex
    98. Case 0, 1
    99. e.Cancel = True
    100. e.NewWidth = LstVw.Columns(e.ColumnIndex).Width
    101. End Select
    102. End Sub
    103. #End Region
    104. #End Region
    105. End Class


    Die DriveManager Class
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class DriveManager
    2. ' Event, das ausgelöst wird, wenn die Laufwerke aufgelistet sind
    3. Public Event DrivesListed As EventHandler(Of Tuple(Of List(Of String), DriveType))
    4. ' Array, das alle Laufwerksinformationen speichert
    5. Public allDrivesInfos() As DriveInfo = DriveInfo.GetDrives()
    6. ' Das ausgewählte Laufwerk
    7. Public SelectedDrive As DriveInfo
    8. ' Enumeration für die verschiedenen Arten von Laufwerken
    9. Public Enum MediaType
    10. Fixed = 1 ' Interne HDDs
    11. External = 2 ' Externe HDDs
    12. Removable = 3 ' USB-Sticks / SD-Karten
    13. End Enum
    14. ' Funktion, die eine WMI-Abfrage je nach Laufwerkstyp zurückgibt
    15. Private Function GetWMIQuery(driveType As MediaType) As String
    16. Select Case driveType
    17. Case MediaType.Fixed
    18. Return "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'"
    19. Case MediaType.External
    20. Return "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='External hard disk media'"
    21. Case MediaType.Removable
    22. Return "SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Removable media'"
    23. Case Else
    24. Return Nothing 'für den Fall, dass kein gültiger Typ angegeben wurde
    25. End Select
    26. End Function
    27. ' Methode zum Auflisten der Laufwerke basierend auf dem angegebenen Typ
    28. Public Sub ListDrives(MediaType As MediaType)
    29. ' Liste, um die gefundenen Laufwerke zu speichern
    30. Dim drivesList As New List(Of String)()
    31. ' Abrufen der WMI-Abfrage für den angegebenen Laufwerkstyp
    32. Dim query As String = GetWMIQuery(MediaType)
    33. ' Prüfen, ob die Abfrage gültig ist
    34. If query <> "" Then
    35. ' Durchführen der WMI-Abfrage
    36. Dim searcher As New ManagementObjectSearcher(query)
    37. searcher.Options.ReturnImmediately = True
    38. ' Durchlaufen der Ergebnisse der WMI-Abfrage
    39. For Each drive As ManagementObject In searcher.Get()
    40. Dim partitionsQuery As String = $"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{drive("DeviceID")}'}} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
    41. Dim partitionSearcher As New ManagementObjectSearcher(partitionsQuery)
    42. ' Durchlaufen der Partitionen für jedes gefundene Laufwerk
    43. For Each partition As ManagementObject In partitionSearcher.Get()
    44. Dim logicalDisksQuery As String = $"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID='{partition("DeviceID")}'}} WHERE AssocClass = Win32_LogicalDiskToPartition"
    45. Dim logicalDisksSearcher As New ManagementObjectSearcher(logicalDisksQuery)
    46. ' Durchlaufen der logischen Laufwerke für jede gefundene Partition
    47. For Each logicalDisk As ManagementObject In logicalDisksSearcher.Get()
    48. Dim driveID As String = logicalDisk("DeviceID").ToString() '& "\"
    49. ' Hinzufügen des Laufwerks, wenn es nicht bereits in der Liste vorhanden ist
    50. If Not drivesList.Any(Function(d) d.StartsWith(driveID)) Then
    51. drivesList.Add(driveID)
    52. End If
    53. Next
    54. Next
    55. Next
    56. ' Sortieren der Laufwerksliste
    57. drivesList.Sort()
    58. ' Bestimmen des Laufwerkstyps
    59. Dim driveType As DriveType = If(MediaType = MediaType.Fixed, DriveType.Fixed, DriveType.Removable)
    60. ' Auslösen des Events und Übergeben der Liste und des Laufwerkstyps
    61. RaiseEvent DrivesListed(Me, Tuple.Create(drivesList, driveType))
    62. ' Erstellen einer lesbaren Zeichenfolge für die Laufwerke
    63. Dim drivesString As String = String.Join(" ", drivesList)
    64. ' Anzeige der Laufwerksliste und des Laufwerkstyps in der Debug-Ausgabe
    65. Debug.WriteLine($"Laufwerke: {drivesString}, Laufwerkstyp: {driveType}")
    66. End If
    67. End Sub
    68. Public Function GetDriveInfo(driveLetter As Char) As DriveInfo
    69. ' Gibt die DriveInfo für das angegebene Laufwerk zurück
    70. Return allDrivesInfos.FirstOrDefault(Function(d) d.Name.StartsWith(driveLetter))
    71. End Function
    72. ' Formatieren der Bytewerte
    73. Public Function FormatSpace(space As Long) As String
    74. Dim units() As String = {"Bytes", "KB", "MB", "GB", "TB"}
    75. Dim index As Integer = CInt(Math.Floor(Math.Log(space, 1024)))
    76. Dim size As Double = space / Math.Pow(1024, index)
    77. Return $"{size:N2} {units(index)}"
    78. End Function
    79. ' Methode um den Computernamen zu ermitteln
    80. Public Shared Function GetComputerName() As String
    81. Return Environment.MachineName
    82. End Function
    83. ' Methode im DriveManager, um das Laufwerk C: zu überprüfen
    84. Public Function IsDriveCSelected() As Boolean
    85. Dim drives As DriveInfo() = DriveInfo.GetDrives()
    86. For Each drive As DriveInfo In drives
    87. If drive.Name.ToUpper() = "C:\" Then
    88. Return True
    89. End If
    90. Next
    91. Return False
    92. End Function
    93. End Class


    Die TreeManager Class
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class TreeManager
    2. Private ReadOnly driveManagerInstance As DriveManager
    3. Private ReadOnly tvDrivesInstance As TreeView
    4. Public Event ShowDriveInfos(driveInfos As DriveInfo)
    5. Public Sub New(driveManager As DriveManager, tvDrives As TreeView)
    6. Me.driveManagerInstance = driveManager
    7. Me.tvDrivesInstance = tvDrives
    8. ' Abonniere das Ereignis des DriveManagers
    9. AddHandler driveManagerInstance.DrivesListed, AddressOf driveManager_DrivesListedForTreeView
    10. ' Ereignisbehandlungsmethode hinzufügen
    11. AddHandler tvDrivesInstance.BeforeSelect, AddressOf tvDrives_BeforeSelect
    12. ' Ereignisbehandlungsmethode hinzufügen
    13. AddHandler tvDrivesInstance.AfterSelect, AddressOf tvDrives_AfterSelect
    14. End Sub
    15. ' Methode zum Aufrufen der Laufwerkliste
    16. Public Sub ListDrives()
    17. ' Zugriff auf das tvDrives Control für die weitere Verarbeitung
    18. If tvDrivesInstance IsNot Nothing Then
    19. ' Hier den TreeView leeren
    20. tvDrivesInstance.Nodes.Clear()
    21. ' Füge den Hauptknoten im Treeview mit einem separaten Icon und den Computernamen hinzu
    22. Dim computerName As String = DriveManager.GetComputerName()
    23. tvDrivesInstance.Nodes.Add("PC", computerName, 1)
    24. ' Laufwerke aus der DriveManager-Klasse abrufen
    25. driveManagerInstance.ListDrives(DriveManager.MediaType.External)
    26. driveManagerInstance.ListDrives(DriveManager.MediaType.Removable)
    27. driveManagerInstance.ListDrives(DriveManager.MediaType.Fixed)
    28. End If
    29. End Sub
    30. ' Ereignisbehandlungsmethode, die aufgerufen wird, wenn die Laufwerke aufgelistet sind
    31. Private Sub driveManager_DrivesListedForTreeView(sender As Object, e As Tuple(Of List(Of String), DriveType))
    32. Dim drivesList As List(Of String) = e.Item1
    33. Dim driveType As DriveType = e.Item2
    34. Dim validDrives As List(Of String) = drivesList.Where(Function(drive) Directory.Exists(drive)).ToList()
    35. ' Ermitteln des Gruppennamens basierend auf dem Laufwerkstyp
    36. Dim groupName As String = GetDriveGroupName(driveType, validDrives)
    37. ' Finde oder erstelle den entsprechenden Knoten basierend auf dem Gruppennamen
    38. Dim groupNode As TreeNode = FindOrCreateGroupNode(groupName)
    39. ' Hinzufügen der Laufwerke zum entsprechenden Knoten im TreeView
    40. For Each drive As String In drivesList
    41. Dim driveNode As New TreeNode(GetDriveDisplayName(drive))
    42. ' Speichern des Laufwerkspfads im Tag des TreeView-Knotens
    43. driveNode.Tag = drive
    44. groupNode.Nodes.Add(driveNode)
    45. ' Setze das Bild für das Laufwerk
    46. SetDriveImageTV(driveNode, driveType, drive)
    47. Next
    48. ' Alle Knoten im TreeView erweitern, um die Laufwerke anzuzeigen
    49. tvDrivesInstance.ExpandAll()
    50. End Sub
    51. ' Methode um die Icons zuzuweisen
    52. Private Sub SetDriveImageTV(driveNode As TreeNode, driveType As DriveType, drivePath As String)
    53. Select Case driveType
    54. Case DriveType.Fixed
    55. If drivePath.ToUpper() = "C:" Then
    56. driveNode.ImageIndex = 5 ' Spezielles Bilde für Laufwerk C:\
    57. Else
    58. driveNode.ImageIndex = 3 ' Standardbild für feste Laufwerke
    59. End If
    60. Case DriveType.Removable
    61. If IsRemovableDriveTV(drivePath) Then
    62. driveNode.ImageIndex = 6 ' Standardbild für SD-Cards / USB-Sticks
    63. Else
    64. driveNode.ImageIndex = 2 ' Standardbild für USB-Festplatten
    65. End If
    66. Case Else
    67. driveNode.ImageIndex = 7 ' Standardbild für andere Laufwerkstypen
    68. End Select
    69. End Sub
    70. ' Methode um die Gruppen zu erstellen
    71. Private Function FindOrCreateGroupNode(groupName As String) As TreeNode
    72. ' Versuche den Gruppenknoten zu finden
    73. Dim nodes As TreeNode() = tvDrivesInstance.Nodes.Find(groupName, False)
    74. ' Überprüfe, ob der Knoten gefunden wurde und mindestens ein Element enthält
    75. If nodes IsNot Nothing AndAlso nodes.Length > 0 Then
    76. ' Der Knoten wurde gefunden, gib ihn zurück
    77. Return nodes(0)
    78. Else
    79. ' Der Knoten wurde nicht gefunden, erstelle einen neuen Knoten und füge ihn hinzu
    80. Dim newNode As New TreeNode(groupName)
    81. ' Setze den Namen des neuen Knotens
    82. newNode.Name = groupName
    83. tvDrivesInstance.Nodes.Add(newNode)
    84. Return newNode
    85. End If
    86. End Function
    87. ' Methode um die Gruppennamen zu erstellen
    88. Public Function GetDriveGroupName(driveType As DriveType, validDrives As List(Of String)) As String
    89. Dim groupName As String = ""
    90. Select Case driveType
    91. ' Gruppenname für Interne Laufwerke
    92. Case DriveType.Fixed
    93. groupName = "Interne Festplatten"
    94. ' Gruppenname für Externe Laufwerke
    95. Case DriveType.Removable
    96. ' Überprüfen auf WechselMedien oder Festplatten
    97. Dim isRemovable As Boolean = validDrives.Any(Function(drive) New DriveInfo(drive).DriveType = DriveType.Removable)
    98. ' Gruppenname basierend auf dem Ergebnis setzen
    99. Select Case isRemovable
    100. Case True
    101. groupName = "USB-Stick / SD-Karten"
    102. Case Else
    103. groupName = "USB-Festplatten"
    104. End Select
    105. Case Else
    106. ' Kein gültiger Typ
    107. groupName = Nothing
    108. End Select
    109. Return groupName
    110. End Function
    111. ' Methode zum formatieren der Laufwerksanzeige im Treeview
    112. Private Function GetDriveDisplayName(drive As String) As String
    113. Dim driveInfo As New DriveInfo(drive)
    114. Dim driveLabel As String = If(Not String.IsNullOrEmpty(driveInfo.VolumeLabel), $"({drive}) {driveInfo.VolumeLabel}", drive)
    115. Return $"{driveLabel}"
    116. End Function
    117. ' Überprüft, ob der Laufwerkstyp wechselbar ist, basierend auf dem Laufwerkspfad
    118. Private Function IsRemovableDriveTV(drivePath As String) As Boolean
    119. Return New DriveInfo(drivePath).DriveType = DriveType.Removable
    120. End Function
    121. Private Sub tvDrives_BeforeSelect(sender As Object, e As TreeViewCancelEventArgs)
    122. ' Überprüfen, ob der ausgewählte Knoten ein Hauptknoten ist
    123. If e.Node.Parent Is Nothing Then
    124. ' Den Klick auf den Hauptknoten verhindern, indem e.Cancel auf True gesetzt wird
    125. e.Cancel = True
    126. End If
    127. End Sub
    128. ' Methode das Laufwerk auszuählen
    129. Private Sub tvDrives_AfterSelect(sender As Object, e As TreeViewEventArgs)
    130. Dim selectedNode As TreeNode = e.Node
    131. ' Überprüfen, ob der ausgewählte Knoten kein Hauptknoten ist
    132. If selectedNode.Parent IsNot Nothing Then
    133. ' Setze das ausgewählte Laufwerk im driveManager
    134. driveManagerInstance.SelectedDrive = New DriveInfo(selectedNode.Tag.ToString())
    135. ' Sende alle Laufwerkinfos an die Listbox auf dem frmMain
    136. RaiseEvent ShowDriveInfos(driveManagerInstance.SelectedDrive)
    137. ' Zeige eine MessageBox, wenn das Laufwerk C:\ ausgewählt wurde
    138. ' Überprüfe, ob Laufwerk C: ausgewählt wurde
    139. If driveManagerInstance.SelectedDrive.Name.ToUpper() = "C:\" Then
    140. ' Zeige eine MessageBox nur für das Laufwerk C:
    141. Dim newMessage As String = $"Sie haben das System-Laufwerk {driveManagerInstance.SelectedDrive.Name} ausgewählt."
    142. MessageBox.Show(newMessage, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
    143. End If
    144. End If
    145. End Sub
    146. End Class

    Bilder
    • treeview-2.jpg

      159,93 kB, 548×315, 41 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Das sieht tatsächlich schon gar nicht mal so schlecht aus.

    Kommentare
    Was ich dir an erster Stelle mitgeben würde, ist dass du unbedingt Dokumentationskommentare verwenden solltest, statt den "normalen" Kommentaren im Code.
    Die machst du mit drei Apostrophen ('), VS (Code) übernimmt dann den Rest für dich. Da schreibst du rein, was die Methoden/Properties usw. machen und beschreibst die Parameter.

    Strings
    Du verwendest jede Menge Strings in deinem Code - soweit alles erstmal in Ordnung.
    Ich würde dir raten, anstatt "Magic Strings" zu verwenden, wie du es gerade tust, lagerer die Strings soweit es geht in Konstanten aus und setze dann erst entsprechende Werte ein.
    Das erhöht mitunter die Wiederverwendbarkeit.

    Du solltest ebenfalls versuchen, Backslashes zu vermeiden. VB lässt das ohne Weiteres zu, aber sobald du versuchst, diese Strings mit einer anderen Sprache zu verwenden, wirst du teils merkwürdige Phänomene erhalten.

    Parameter
    Mir ist aufgefallen, dass du an ein oder zwei Stellen einen Parameter nach einem Datentypen benannt hast. Visual Basic ist case insensitive und kennt den Unterschied, weshalb das funktionieren mag.
    Es ist allerdings nicht sonderlich gut zu lesen. Hier solltest du aussagekräftigere Namen verwenden und nach Möglichkeit (auch wenn es VB egal ist) auf Groß-/Kleinschreibung achten.

    Klare Rückgabewerte
    Dim query As String = GetWMIQuery(MediaType)
    Deine Methode gibt zwar einen String zurück, aber auch null. Das ist nicht dokumentiert und könnte beim Überfliegen übersehen werden.
    Was hier besser wäre, ist wenn du das A) dokumentierst und B) als Rückgabetyp string? verwendest. Dann ist es sowohl im Code, als auch in der Doku ersichtlich, was genau diese Method zurückgibt.

    Im gleichen Zuge, solltest du auch auf null oder nothing prüfen. Wenn der String tatsächlich null ist, dann könnte das einen Fehler werfen oder fehlerhaftes Verhalten aufzeigen.

    Klassenstruktur und Verkapselung
    Grundsätzlich finde ich, ist deine Klasse sauber und logisch aufgeteilt. Großes Lob dafür, ich habe schon viiieel kleinere und unübersichtlichere Klassen geschrieben gesehen.

    Allerdings solltest du drauf achten, öffentliche Eigenschaften immer als soche zu deklarieren. Entweder mit Getter/Setter, oder als property.
    Das dient der Verkapselung deiner Daten. Das ist insbesondere dann wichtig, wenn du ungefilterten Input filtern/parsen musst.

    Dazu solltest du vermeiden, nested Klassen/Enums zu schreiben. Es gibt Fälle, wo es Sinn macht, das Namespace nicht mit irgendwelchen Sachen vollzumüllen, aber wenn das ein enum ist, den auch andere (Klassen) verwenden, dann leg sie am besten direkt ins Namespace.
    Wenn ich mehr als ein/zwei Mal MyFoo.EnumType schreiben muss, dann habe ich direkt das Verlangen, die Struktur komplett zu refactoren. Macht den ganzen Code einfach nur schwer zu verstehen.

    Nesting und Vereinfachung von Abfragen
    Das ist mMn noch subjektiver als die meisten anderen Themen, erwähnen möchte ich es dennoch.

    Du schreibst:

    VB.NET-Quellcode

    1. if x isnot nothing then
    2. ' do stuff
    3. ' do stuff
    4. 'do stuff
    5. end if


    viel lesbarer wird es (find ich), wenn man die If invertiert.

    VB.NET-Quellcode

    1. if x is nothing then return
    2. ' or
    3. if x is nothing then
    4. return
    5. end if
    6. ' do stuff
    7. ' do stuff
    8. 'do stuff


    Implicit Typing
    Ich habe es hier im Forum kürzlich wieder erwähnt.
    Lasst den Compiler ruhig die Arbeit machen.

    Anhand des Methoden-/Variablennamens oder der Doku-Kommentare sollte ersichtlich sein, was die Methode macht.
    Dementsprechend ist aus dem Kontext schon klar, was die (wichtigsten) Parameter sind.

    Spar dir das as TreeViewNode und schreibe schlicht Dim selectedNode = e.Node. Der Compiler muss schließlich auch was für seine Brötchen tun. Einfaches lexisches Analysieren und deinen Code in Tokens brechen reicht heutzutage nimmer. Ich muss ja auch Softwareingenieur, -Tester und Release-Manager spielen :)

    Debug-Fehler-Nachrichten
    Am besten gleich sein lassen.
    Wenn du einen Fehler ausgibst und das Programm von Otto-Normal-Verbrauchen genutzt werden soll, wollen die keinen Stack Trace (den es bei einem optimierten Build ohnehin nicht wirklich* gibt) sehen. Die denken, der Rechner sei in die Luft geflogen.
    Benutz einen Logger wie Serilog o.Ä. und schmeiß da deine Stacktraces rein als Debug-Ausgabe. Die Fehlermeldung alleine sollte reichen.

    Zu guter Letzt: Testen
    Das ist ein Thema, das hört kein Softwaremensch gerne (außer vielleicht der @RodFromGermany :p).
    Es ist aber ein elementarer Teil unserer Aufgabe/unseres Hobby. Wir wollen schließlich keine Software rausgeben, die unentdeckte Fehler hat.

    Schreib Unit Tests (MSTest ist dafür super). Es gibt auch Tools, die wie Affen wild in deiner UI rumklicken und auf die Tastatur rumhacken - um eben unerwartete UI-Fehler aufzudecken.
    Da gibt's zahlreiche Themen im Internet zu. Für .net habe ich persönlich nie eins gebraucht, aber für Qt/C++ gibt's z.B. Squish.




    Ich find's übrigens super, dass du nach Feedback fragst! Nur so kann man dazulernen.
    Man geht immer mit einem Tunnelblick an seinen eigenen Code. Man überliest/übersieht/ignoriert Sachen, oder hat einfach einen Spaten im Gehirn stecken, der genau die zwei Neuronen blockiert, die man braucht, um das Problem zu erkennen.
    Diesen Tunnelblick haben Fremde (ob nun fremde Menschen wie wir, oder Kollegen, die projektfremd sind) selten bis gar nicht.

    Wenn du was von dem Feedback gebrauchen kannst, freut es mich. Wenn du das liest und dir denkst "was'n Spinner. Leute gibt's..." ist das natürlich auch in Ordnung :D Da bin ich nicht so empfindlich

    EDIT: Scheinbar bin ich zu blöd, für die Line-Funktion im Editor. Kann mich da jemand aufschlauen? Egal ob ich's leer lasse oder was eingebe, der parst das nicht...

    Inhalt zwischen den Line-Tags entfernt, um eine Linie anzuzeigen ~VaporiZed
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    @siycah
    Moin moin und Danke für dein Feedback. :rolleyes:

    Ja wo fange ich an.
    Ein Logger: Ich habe einen, den ich mir selbst geschrieben habe, nur eben hier bzgl der Übersicht weggelassen, wie auch den USB-Monitor, der das Treeview immer aktuell halten würde.
    Die DebugAusgaben mache ich mir immer um zu sehen ob das auch ankommt, was ich da erwarte. Hatte gerade am Anfang immer Probleme weiter zukommen, weil einfach nicht das ankam und so meine Codes nie liefen.
    In der Release-Version sind die ja eh weg.


    So etwas meinst du, gelle. ;)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Const internelDrives As String = "Interne Festplatten"
    2. Private Const externelDrives As String = "USB Festplatten"
    3. Private Const removableDrives As String = "USB Sticks / SD-Karten"


    XML-Quellcode

    1. ''' <summary>
    2. ''' Initialisiert eine neue Instanz der TreeManager-Klasse.
    3. ''' </summary>
    4. ''' <param name="driveManager">Die Instanz des DriveManagers.</param>
    5. ''' <param name="tvDrives">Die Instanz des TreeView-Controls.</param>



    Die <summary> fand ich jetzt hier ein wenig viel aber eigentlich haste ja Recht, sollte mir ja selber helfen alte Codes wieder zu lesen.
    Deine anderen Anmerkungen werde ich in meinem "Übungsprojekt" nochmal überarbeiten. :thumbup:
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    ich finde, man soll immer sparsam dokumentieren - auch Doku-Kommentare.
    Zuviele Kommentare (auch Doku-Kommentare) machen Code unleserlich
    • wenn sie einfach nur das nachlabern, was sowieso prominent im Code steht
      wichtiger als schlau daherzukommentieren ist, seinen Code sinnig zu benamen, dass er sich selbst erklärt - ohne Comment
    • oder wenn sie gar inhaltlich falsch sind.
      das passiert insbesondere dann, wenn Code nachgebessert wird (also sehr oft).
    Keinesfalls sollten Kommentare dasjenige nochmal hinlabern, was sowieso im Code steht.
    Also genau sowas ist mir ein Graus:

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Initialisiert eine neue Instanz der TreeManager-Klasse.
    3. ''' </summary>
    4. ''' <param name="driveManager">Die Instanz des DriveManagers.</param>
    5. ''' <param name="tvDrives">Die Instanz des TreeView-Controls.</param>
    6. Public Sub New(driveManager As DriveManager, tvDrives As TreeView)
    7. '...

    • zeile #2: enthält keine Information. Bzw wer nicht weiss, dass Sub New eine neue Instanz initialisiert, sollte erst garkein Code angucken dürfen.
    • #4: enthält keine Information. Das der Parameter ein DriveManager ist, steht ja im Code selbst
    • #5 enthält keine Information. Das der Parameter ein TreeView ist, steht ja im Code selbst
    Also da würde ich dir genau zustimmen, wenn du sagst:

    Amelie schrieb:

    Die <summary> fand ich jetzt hier ein wenig viel...
    und auch dabei bleiben



    Hingegen sowas

    VB.NET-Quellcode

    1. ' Methode zum Aufrufen der Laufwerkliste
    2. Public Sub ListDrives()
    ist durchaus eines Doku-Comments wert.
    Nur soll der Comment auch sagen, was die Methode tut - nicht einfach nochmal hinlabern, was im Code sowieso schon steht - also tätichs mir so wünschen:

    VB.NET-Quellcode

    1. ''' <summary>Legt im Treeview Nodes an mit Laufwerks-Informationen</summary>
    2. Public Sub ListDrives()
    Noch besser aber wäre, wenn du der Methode einen Namen gibst, der sagt, was sie tut:

    VB.NET-Quellcode

    1. Public Sub PopulateDrivesTreeview()
    und gut ist.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @ErfinderDesRades

    Ehrlich gesagt, tut ich mich immer etwas schwer die "richtigen / passenden" Worte für solche Kommentare zu finden.
    Denke aber das es mit der Zeit besser wird, wenn ich da dranbleibe. ;)

    Das hier finde ich einen guten Kompromiss bzgl der Länge der Kommentare / Summarys.

    XML-Quellcode

    1. ' Methode zum Aufrufen der Laufwerkliste
    2. ''' <summary>Legt im Treeview Nodes an mit Laufwerks-Informationen</summary>
    3. Public Sub ListDrives()
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh: