Detect external disk drive ...

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Detect external disk drive ...

    Hi,

    ich habe an meinem PC interne Festplatten (z.Teil als Partition der Systemresidenz mit festem Laufwerksbuchstaben), externe Festplatten über USB, und auch USB Sticks ...

    Jetzt würde ich gern herausfinden, ob ein Laufwerksbuchstabe auf eine externe Festplatte verweist. Hier mein Code:

    VB.NET-Quellcode

    1. 'Load drive list
    2. Dim allDrives() As DriveInfo = DriveInfo.GetDrives()
    3. For Each d As DriveInfo In allDrives
    4. Debug.Print("d.Name=" & d.Name)
    5. If d.IsReady Then
    6. Debug.Print("d.VolumeLabel=" & d.VolumeLabel & NewLine &
    7. "d.DriveType=" & d.DriveType.ToString & NewLine &
    8. "d.DriveFormat=" & d.DriveFormat & NewLine &
    9. "d.Root=" & d.RootDirectory.Name & NewLine &
    10. "d.=IsReady" & d.IsReady.ToString & NewLine)
    11. Dim t = d.GetType()
    12. Debug.Print("t.Attributs=" & t.Attributes.ToString & NewLine &
    13. "t.BaseType=" & t.BaseType.ToString & NewLine)
    14. Else
    15. Debug.Print("")
    16. End If


    Die Ausgabe sieht wie folgt aus:

    d.Name=C:\
    d.VolumeLabel=WINRES
    d.DriveType=Fixed
    d.DriveFormat=NTFS
    d.Root=C:\
    d.=IsReadyTrue

    t.Attributs=AutoLayout, AnsiClass, Class, Public, Sealed, Serializable, BeforeFieldInit
    t.BaseType=System.Object

    d.Name=E:\
    d.VolumeLabel=ETOSH
    d.DriveType=Fixed
    d.DriveFormat=NTFS
    d.Root=E:\
    d.=IsReadyTrue

    t.Attributs=AutoLayout, AnsiClass, Class, Public, Sealed, Serializable, BeforeFieldInit
    t.BaseType=System.Object

    d.Name=G:\
    d.VolumeLabel=EXTUSB
    d.DriveType=Removable
    d.DriveFormat=FAT32
    d.Root=G:\
    d.=IsReadyTrue

    t.Attributs=AutoLayout, AnsiClass, Class, Public, Sealed, Serializable, BeforeFieldInit
    t.BaseType=System.Object

    Quellcode



    C: ist eine interne Festplatte, F: ist eine externe Festplatte udn G: ist ein USB Stick.

    Den USB Stick erkenne ich an "d.DriveType=Removable"

    Aber soviel ich auch suche ... ich finde keine Unterscheidung zwischen einer internen Festplatte (bzw. Partition) und einem externen Laufwerk.

    Ein paar Attribute, die man mit Gettype bekommt, habe ich spaßeshalber ausgegeben ... aber wie man sieht ist da nix Brauchbares dabei ...

    Kann jemand meine Suche abkürzen ? Vielleicht gibt es ja auch keine Unterscheidung ... damit könnte ich zur Not leben, schließlich kenne ich die Label meiner Festplatten einigermaßen ... :)

    Aber schöner wäre das schon, wenn ich das per Programm ermitteln könnte.

    LG
    Peter
    @Peter329 Ich detektiere USB-Laufwerke beim An- bzw. abstecken, also nach Starten des Programms:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Button und Multiline-TextBox
    2. Imports System.IO
    3. Public Class Form1
    4. ''' <summary>
    5. ''' Liste der aktuell vorhandenen Laufwerke
    6. ''' </summary>
    7. ''' <remarks></remarks>
    8. Private allDrives As New List(Of DriveInfo)
    9. Private DriveNameToFind As String
    10. Public Sub New()
    11. Me.InitializeComponent()
    12. Me.allDrives = DriveInfo.GetDrives().ToList()
    13. End Sub
    14. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    15. Me.TextBox1.Clear()
    16. End Sub
    17. Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
    18. MyBase.WndProc(msg)
    19. Const WM_DEVICECHANGE As Integer = &H219
    20. Const DBT_DEVICEARRIVAL As Integer = &H8000
    21. Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
    22. Const DBT_DEVNODES_CHANGED As Integer = 7
    23. Dim wParam As Integer = msg.WParam.ToInt32()
    24. If msg.Msg = WM_DEVICECHANGE Then
    25. If wParam = DBT_DEVICEARRIVAL Then
    26. 'Laufwerke suchen
    27. For Each drive As String In Directory.GetLogicalDrives
    28. Me.DriveNameToFind = drive
    29. Dim found As DriveInfo = Me.allDrives.Find(AddressOf find_driveinfo)
    30. If found Is Nothing Then
    31. found = New DriveInfo(drive)
    32. Me.TextBox1.AppendText(String.Format("Ein USB-Gerät wurde hinzugefügt: {0}{1}", found.VolumeLabel, Environment.NewLine))
    33. 'Laufwerk ist neu, Laufwerk zu "bereits vorhanden" hinzufügen
    34. Me.allDrives.Add(found)
    35. End If
    36. Next
    37. ElseIf wParam = DBT_DEVICEREMOVECOMPLETE Then
    38. ' alle Laufwerke aus der Liste prüfen
    39. Dim temp As List(Of DriveInfo) = DriveInfo.GetDrives().ToList()
    40. For Each drive As DriveInfo In Me.allDrives
    41. Me.DriveNameToFind = drive.Name
    42. Dim lost As DriveInfo = temp.Find(AddressOf find_driveinfo)
    43. If lost Is Nothing Then
    44. Me.TextBox1.AppendText(String.Format("Ein USB-Gerät wurde entfernt: {0}{1}", drive.Name, Environment.NewLine))
    45. 'Laufwerk wird in der Liste nicht mehr gefunden: Laufwerk aus der Liste löschen
    46. Me.allDrives.Remove(drive)
    47. Exit For
    48. End If
    49. Next
    50. ElseIf wParam = DBT_DEVNODES_CHANGED Then
    51. Me.TextBox1.AppendText("Ein USB-Gerät wurde gesteckt / entfernt." & Environment.NewLine)
    52. End If
    53. End If
    54. End Sub
    55. ' Suchfunktion für die Liste, da eine Property verglichen wird
    56. Private Function find_driveinfo(ByVal drive As DriveInfo) As Boolean
    57. Return drive.Name = Me.DriveNameToFind
    58. End Function
    59. End Class
    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!
    Zusammengeschustert von stackoverflow, um nur die USB-Festplatten rauszubekommen:

    VB.NET-Quellcode

    1. Dim LettersOfUsbDrives As New List(Of Char)
    2. Dim ManagementObjectSearcher As New ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'")
    3. For Each QueryObject As ManagementObject In ManagementObjectSearcher.Get()
    4. For Each DiskPartitionObject As ManagementObject In QueryObject.GetRelated("Win32_DiskPartition")
    5. For Each LogicalDiskObject As ManagementObject In DiskPartitionObject.GetRelated("Win32_LogicalDisk")
    6. LettersOfUsbDrives.Add(LogicalDiskObject("name").ToString(0))
    7. Next
    8. Next
    9. Next
    10. For Each Drive In IO.DriveInfo.GetDrives().Where(Function(x) x.IsReady AndAlso x.DriveType = IO.DriveType.Fixed AndAlso LettersOfUsbDrives.Contains(x.Name(0)))
    11. MessageBox.Show(Drive.Name & " scheint eine externe Festplatte zu sein.")
    12. Next
    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.
    erst mal vielen Dank für deinen Spoiler.

    Das Programm ist prima, wenn man feststellen will, ob USB Laufwerke hinzugefügt oder entfernt wurden. Klasse !

    Aber leider trifft das nicht ganz mein Problem.

    Ich will wissen, ob ein Laufwerk vom DriveType=Fixed eine eingebaute Festplatte / eine Partition einer Festplatte ist ODER ob es sich um eine externe Festplatte handelt, die über einen USB Port "angesteckt" ist. Beide haben blöderweise den GLEICHEN DriveType=Fixed .... und ich sehe auch sonst keinerlei Merkmale, die eine Unterscheidung erlauben würden.

    Warum ich das wissen will ? Na ja, die Routine ist Teil eines BackupProgramms (Incremetal Backup für Verzeichnisbäume) ... und da wäre es ja nicht gut, wenn das Sicherungsmedium ein "internes" Laufwerk ist. In diesem Fall würde ich gern eine Warnung ausgeben. Denn wenn der PC abbrennt oder gestohlen wird etc. etc., dann sind sowohl die Source als auch die Backup Daten weg. Natürlich kann ich einfach sagen, dass der Anwender eben "schlau" genug sein muss, um ein "vernünftiges" (also kein internes) Ziellaufwerk auszuwählen ... aber man kann sich halt auch leicht "verklicken" ... Und das merkt man dann möglicherweise erst im Schadensfall ! Eine Warnung wäre also schon nicht gar so schlecht ...

    Ich hoffe, ich habe mein Problem verständlich machen können. Umgehen kann ich das Problem alle mal, indem ich halt eine Liste der VolumeLabel der internen Laufwerke "von Hand" fest einprogrammiere ... aber das ist halt eine ziemlich blöde Lösung !

    LG
    Peter

    [edit]
    P.S.: Den Beitrag von @VaporiZed habe ich erst nach Absenden meines Posts gelesen ... das problere ich jetzt aus ...

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

    @VaporiZed Wenn ich eine externe USB-Platte "normal" an einem USB-Port anschließe, wird sie erkannt.
    Schließe ich eine externe USB-Platte über ein QuickPort XT HC PRO an, wird die nicht erkannt.
    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!

    Peter329 schrieb:

    Das Programm
    ist das von RfG oder das Snippet von mir? Ok, hat sich geklärt. Damit war RfGs Code gemeint.
    Wird denn mit meinem dem von mir geposteten Snippet die externe HDD/SSD als solche erkannt oder nicht? Oder wird da noch anderes Zeug erkannt? Es ist ja ne Anzeige von Übereinstimmungen aus USB-Laufwerken und Festplatten.
    @RodFromGermany: Da kann ich nur hoffe, dass @Peter329 so'n Teil nicht hat :rolleyes: . Nee, Spassssss beiseite. Wird das Teil an sich als Gerät erkannt? Weil: Die HDD ist ja über SATA wahrscheinlich an die Docking Station gebunden, oder?
    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.
    Mein Kommentar bezog sich auf das Snippet von VaporiZed.

    VaporiZed schrieb:

    Die HDD ist ja über SATA wahrscheinlich an die Docking Station gebunden, oder?
    Weiß ich nicht genau, das Ding hängt an einem USB-Port am Rechner, da stecke ich meine "losen" externen Platten dran; hat mir mein Sohn geschenkt, ich hab mich nicht mit dessen "innenleben" beschäftigt.
    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!
    Also die Routine von @VaporiZed funktioniert prima.

    Allein die Message " scheint eine externe Festplatte zu sein." nährt nicht gerade meine Vertrauen in die Zuverlässigkeit der Routine ...

    Ich hab die Sache jetzt noch ein bissl umgemodelt, denn ich will natürlich neben externen Festplatten auch USB Sticks als Speichermedium zulassen ...

    VB.NET-Quellcode

    1. 'Load drive list
    2. Dim allDrives() As DriveInfo = DriveInfo.GetDrives()
    3. Dim myDeviceType As String
    4. For Each d As DriveInfo In allDrives
    5. If Not d.IsReady Then Continue For
    6. Select Case d.DriveType
    7. Case IO.DriveType.Fixed
    8. myDeviceType = If(LettersOfUsbDrives.Contains(d.Name(0)), "EXT", "INT")
    9. Case IO.DriveType.Removable : myDeviceType = "USB"
    10. Case Else : Continue For
    11. End Select
    12. dgv.Rows.Add(myDeviceType,
    13. d.Name,
    14. d.VolumeLabel,
    15. d.RootDirectory.Name)
    16. Next


    Funktioniert in meiner hausbackenen Umgebung bisher fehlerfrei.

    Vielen Dank an die Ratgeber und Daumen hoch ! :)

    LG
    Peter

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

    Moin moin

    Ich hatte mal das mit Eurer Hilfe gemacht, weil ich eigentlich SD-Karten ermitteln wollte.
    Weiß jetzt nicht ob das dem gesuchten entspricht.
    Suche gerade nach dem Code auf meiner Backupplatte.

    Edit: Der Code
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Management
    3. Imports System.Windows.Forms
    4. Public Class Frm_Laufwerke
    5. Public strResult As String
    6. Public strName As String
    7. Public strSize As String
    8. Public strfSize As String
    9. Public strLWb As String
    10. Public strDeviceID As String
    11. Private Sub optionen_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    12. getusbdrive()
    13. End Sub
    14. Public Sub getusbdrive()
    15. Try 'Interne Festplatten
    16. Dim propName1() As String = "DeviceID SerialNumber Name".Split
    17. Dim query1() As String = {"SELECT * FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'", "", "", ""}
    18. For Each drive As ManagementObject In New ManagementObjectSearcher(query1(0)).Get
    19. query1(1) = String.Format("ASSOCIATORS OF {0}Win32_DiskDrive.DeviceID='{2}'{1} WHERE AssocClass = Win32_DiskDriveToDiskPartition", "{", "}", drive(propName1(0)).ToString)
    20. For Each partition As ManagementObject In New ManagementObjectSearcher(query1(1)).Get
    21. query1(2) = String.Format("ASSOCIATORS OF {0}Win32_DiskPartition.DeviceID='{2}'{1} WHERE AssocClass = Win32_LogicalDiskToPartition", "{", "}", partition(propName1(0)).ToString)
    22. For Each disk As ManagementObject In New ManagementObjectSearcher(query1(2)).Get
    23. strLWb = disk(propName1(2)).ToString
    24. strResult = (strLWb.Substring(0, 1))
    25. Dim info As IO.DriveInfo = New IO.DriveInfo(strResult)
    26. strName = info.VolumeLabel
    27. strfSize = convert(CDbl(info.TotalFreeSpace), "0.00")
    28. strSize = convert(CDbl(info.TotalSize), "0.00")
    29. lv_inhdds.Items.Add(New ListViewItem({strLWb, strName, strSize, strfSize}))
    30. Next
    31. Next
    32. Next
    33. 'Externe USB Festplatten
    34. Dim propName() As String = "DeviceID SerialNumber Name".Split
    35. Dim query() As String = {"SELECT * FROM Win32_DiskDrive WHERE MediaType='External hard disk media'", "", "", ""}
    36. For Each drive As ManagementObject In New ManagementObjectSearcher(query(0)).Get
    37. query(1) = String.Format("ASSOCIATORS OF {0}Win32_DiskDrive.DeviceID='{2}'{1} WHERE AssocClass = Win32_DiskDriveToDiskPartition", "{", "}", drive(propName(0)).ToString)
    38. For Each partition As ManagementObject In New ManagementObjectSearcher(query(1)).Get
    39. query(2) = String.Format("ASSOCIATORS OF {0}Win32_DiskPartition.DeviceID='{2}'{1} WHERE AssocClass = Win32_LogicalDiskToPartition", "{", "}", partition(propName(0)).ToString)
    40. For Each disk As ManagementObject In New ManagementObjectSearcher(query(2)).Get
    41. strLWb = disk(propName(2)).ToString
    42. strResult = (strLWb.Substring(0, 1))
    43. Dim info As IO.DriveInfo = New IO.DriveInfo(strResult)
    44. strName = info.VolumeLabel
    45. strfSize = convert(CDbl(info.TotalFreeSpace), "0.00")
    46. strSize = convert(CDbl(info.TotalSize), "0.00")
    47. lsv_usbhdds.Items.Add(New ListViewItem({strLWb, strName}))
    48. Next
    49. Next
    50. Next
    51. 'Externe USB Sticks und Externe SD-Card-Reader
    52. Dim propName3() As String = "DeviceID SerialNumber Name".Split
    53. Dim query3() As String = {"SELECT * FROM Win32_DiskDrive WHERE MediaType='Removable media'", "", "", ""}
    54. For Each drive As ManagementObject In New ManagementObjectSearcher(query3(0)).Get
    55. 'Dim strLWb As String
    56. query3(1) = String.Format("ASSOCIATORS OF {0}Win32_DiskDrive.DeviceID='{2}'{1} WHERE AssocClass = Win32_DiskDriveToDiskPartition", "{", "}", drive(propName3(0)).ToString)
    57. For Each partition As ManagementObject In New ManagementObjectSearcher(query3(1)).Get
    58. query3(2) = String.Format("ASSOCIATORS OF {0}Win32_DiskPartition.DeviceID='{2}'{1} WHERE AssocClass = Win32_LogicalDiskToPartition", "{", "}", partition(propName3(0)).ToString)
    59. For Each disk As ManagementObject In New ManagementObjectSearcher(query3(2)).Get
    60. strLWb = disk(propName3(2)).ToString
    61. strResult = (strLWb.Substring(0, 1))
    62. Dim info As IO.DriveInfo = New IO.DriveInfo(strResult)
    63. strName = info.VolumeLabel
    64. strfSize = convert(CDbl(info.TotalFreeSpace), "0.00")
    65. strSize = convert(CDbl(info.TotalSize), "0.00")
    66. lsv_usbdrive.Items.Add(New ListViewItem({strLWb, strName}))
    67. Next
    68. Next
    69. Next
    70. Catch ex As Exception
    71. End Try
    72. End Sub
    73. Public Function convert(ByVal dblbytes As Double, ByVal strconverted As String) As String
    74. Dim arrPosForm() As String = {"Bytes", "Kilobyte", "Megabyte", "Gigabyte", "Terabyte"}
    75. For i As Integer = arrPosForm.Length - 1 To 0 Step -1
    76. If dblbytes > 1024 ^ i Then
    77. dblbytes /= 1024 ^ i
    78. Return dblbytes.ToString(strconverted) & " " &
    79. arrPosForm(i)
    80. End If
    81. Next i
    82. Return dblbytes.ToString(strconverted) & " Bytes"
    83. End Function
    84. End Class

    Bilder
    • USBHDD-1.jpg

      133,58 kB, 498×479, 47 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

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

    Peter329 schrieb:

    Allein die Message " scheint eine externe Festplatte zu sein." nährt nicht gerade meine Vertrauen in die Zuverlässigkeit der Routine
    Ich hätte den Text auch anders formulieren können. Das Problem ist nur: Ich hab bei mir nicht allzu viele Laufwerke, um alles exzessiv zu testen. Daher hab ich die Formulierung etwas vorsichtig gehalten.

    btw:

    VB.NET-Quellcode

    1. For Each d As DriveInfo In allDrives
    2. If Not d.IsReady Then Continue For
    Solche Dinger änder ich gern zu For Each d As DriveInfo In allDrives.Where(Function(x) x.IsReady)
    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.