Cell Phone als USB device

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Cell Phone als USB device

    Hi,

    ich habe ein (bescheidenes) cell phone ... und ab und zu mache ich damit Photos und möchte die auf meinen PC hochladen und auf dem cell phone löschen.

    Klar, das kann man mit dem Windows Explorer machen ... aber das ist recht mühsam und deswegen möchte ich das mit einem VB Programm lösen.

    Am liebsten wäre es mir, wenn ich dem cell phone einen LAUFWERKSBUCHSTABEN zuordnen könnte und das Dingens dann ganz normal über VB.Net Methoden ansprechen könnte. So wie das bei einen Netzlaufwerk ja auch funktioniert. Wenn das gehen sollte, dann wäre ich mehr als happy.

    Ansonsten würde mir auch ein VB.Net Programm ausreichen, dass die FileNamen in meinem .../DCIM/Camera Ordner anzeigt, Files nach Auswahl auf meinen PC kopiert und auf dem cell phone löscht.

    Mit anderen Worten: ich müsste eine geignete Methode haben, die das Verzeichnis des Ordners auf dem Cell phone ausliest, eine zweite, die Files vom cell phone auf den PC kopiert und eine dritte, die Files auf dem cell phone löscht.

    Ist das zuviel verlangt ? Im dritten Jahrtausend A.D. sollte das ja eigentlich möglich sein. :)

    Für freundliche und nachsichtige Ratschläge wäre ich wie immer sehr dankbar.

    LG
    Peter
    Jau, das war genau der Link, den ich gesucht hatte.

    Man muss COM-Objekte verwenden ... und dann klappt das auch hervorragend !

    Ich habe mal hier mein Coding eingestellt, weil der von @petoad eingestellt Link of Code verweist, der in C# geschrieben ist und zudem ein wichtiger Hinweis bezüglich der verwendeten Reference fehlt:

    VB.NET-Quellcode

    1. Dim ToBasePath As String = "... your target directory ... "
    2. Dim ToSubdirectory As String = "Camera"
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. 'Check target path
    5. If Not Directory.Exists(ToBasePath) Then
    6. lblMessage.Text = "*** ToBasePath does not exist."
    7. Exit Sub
    8. End If
    9. 'Delete target directory, if it exists
    10. Dim ToDirectory = IO.Path.Combine(ToBasePath, ToSubdirectory)
    11. If Directory.Exists(ToDirectory) Then
    12. Try
    13. Directory.Delete(ToDirectory, recursive:=True)
    14. Catch ex As Exception
    15. lblMessage.Text = "*** Cannot delete existing ToDirectory"
    16. MessageBox.Show(ex.Message)
    17. Exit Sub
    18. End Try
    19. End If
    20. 'Select COM folder on cell phone
    21. 'Note: BrowserForFolder requires:
    22. ' + Reference to the COM Component "Microsoft Shell Controls and Automation"
    23. ' + Include Shell32 Namespace
    24. '"Microsoft Shell Controls and Automation" causes error BC31541 (Interop type cannot be added).
    25. 'To avoid this error, click this reference and set:
    26. ' Accept Interop Types=False
    27. Dim shell = New ShellClass()
    28. Dim Hwnd As Integer
    29. Dim FromFolder = shell.BrowseForFolder(Hwnd, "Choose folder", 0, 0)
    30. If FromFolder Is Nothing Then
    31. lblMessage.Text = "*** OK, cancelled."
    32. Exit Sub
    33. End If
    34. 'This is how to get the real path form the folder object, which is a cryptic expression:
    35. 'Dim fi As FolderItem = (TryCast(FromFolder, Folder3)).Self
    36. 'Dim path = fi.Path 'Just for your info
    37. 'Note: FromFolder is a COM-Object, so it cannot be used like a .NET directory
    38. 'Copy all files from cell phone to PC directory
    39. Dim ToFolder = Path2Folder(ToBasePath) 'Convert target path to a 'COM folder
    40. CopyFiles(FromFolder, ToFolder) 'Copy all files
    41. 'Check result of operation
    42. If Directory.Exists(ToDirectory) Then
    43. Dim FileList = Directory.GetFiles(ToDirectory)
    44. lblMessage.Text = "OK, completed cnt=" & FileList.Count.ToString("n0")
    45. Else
    46. lblMessage.Text = "*** No target file created."
    47. End If
    48. End Sub
    49. Public Sub CopyFiles(ByVal srcFolder As Folder, ByVal dstFolder As Folder)
    50. For Each currFolderItem As FolderItem In srcFolder.Items()
    51. If currFolderItem.Name = ToSubdirectory Then
    52. 'Default = 0 No Options specified
    53. 'NoProgressDialog = 4 Do Not display a Progress DialogBox
    54. 'RenameTarget = 8 Rename the Target File If a File exists at the Target Location With the same Name
    55. 'AutoYesToAll = 16 Click "Yes to All" In any DialogBox displayed
    56. 'PreserveUndo = 64 Preserve undo Information, If possible
    57. 'WildcardOnly = 128 Perform the Operation only If a Wildcard Filename (*.*) Is specified
    58. 'HideProgressFileNames = 256 Display a Progress DialogBox but Do Not show the Filenames
    59. 'NoNewFolderConfirmation = 512 Do Not confirm the creation Of a New Directory If needed
    60. 'NoUIonError = 1024 Do Not display a User Interface If an Error occurs
    61. 'DisableRecursion = 4096 Disable Recursion
    62. 'NoGroupCopy = 9182 Do Not copy connected Files as a Group. Only copy the specified Files
    63. Dim myOption As Integer = 16
    64. dstFolder.CopyHere(currFolderItem, myOption)
    65. End If
    66. Next
    67. End Sub
    68. Public Function Path2Folder(ByVal path As String) As Folder
    69. 'Directory.CreateDirectory(path)
    70. Dim shell As Shell = New ShellClass()
    71. Return shell.[NameSpace](path)
    72. End Function


    Funktioniert prima ... Ich hoffe, ich habe alles gut kommentiert. Vielleicht hilft mein Coding ja anderen Leuten, die ein ähnliches Problem haben. :)

    Eine Kleinigkeit stört mich noch ein wenig ... wie kann ich denn den BrowseForFolder Dialog mit einem Anfangsdirectory starten lassen ?

    Zur Zeit erhalte ich das angehängte Fensterchen ...

    ... und da muss ich mich jedesmal durchhangeln, bis ich auf das cell phone Camera Verzeichnis komme ...

    This PC - my cell phone - DCIM

    Mit anderen Worten: wie kriege ich denn "This PC" in eine Pfadangabe ?

    Das sollte doch auch einfacher gehen ... oder etwa nicht ? :)

    Und noch eine Kleinigkeit: wo bekomme ich denn die Enumeration für die folder.CopyHere Methode her (Default, NoProgressDialog, etc.) ? Natürlich könnte ich die selbst kodieren aber das ist ja nun nicht gerade die feine Art ...

    LG
    Peter
    Bilder
    • s 2021-06-02 13-45-439.jpg

      12,4 kB, 311×368, 16 mal angesehen

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

    Der Ausgangspunkt für den BrowseForFolder Dialog ist .RootFolder
    Aber wenn du damit in einem bestimmten Verzeichnis startest wird alles darüber nicht mehr angezeigt.
    Sprich ab 'C:\Testverzeichnis' abwärts aber 'C:\' nicht.
    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.

    ThomasG82 schrieb:

    Der Ausgangspunkt für den BrowseForFolder Dialog ist .RootFolder


    Ich hab das (mangels besserm Wissens) wie folgt versucht:

    VB.NET-Quellcode

    1. Dim FromFolder = shell.BrowseForFolder(Hwnd, "Choose folder", 0, "This PC")


    Die Syntax wird zwar akzeptiert. Aber leider funktioniert das nicht ! Es wird nach wie vor die oberste Hierachiestufe angezeigt.

    Wenn ich da einen "handelsüblichen" Pfad eintrage z.B. C:\test\data, dann klappt das aber schon.

    Deshalb meine Frage: wie verweise ich denn auf einen Pfad, der mit This PC beginnt ?

    Wahrscheinlich ist meine Frage saublöde und offenbart (ein ums andere Mal) mein grenzenloses Nichtwissen ... deshalb bitte ich ja auch regelmäßig um nachsichtige Ratschläge ... :)

    Gibt es Hoffnung für mich ?

    LG
    Peter
    Durch eine kleine Schleife hab ich es herausgefunden: Dim FromFolder = shell.BrowseForFolder(Hwnd, "Choose folder", 0, 17)
    Bin im Netz drauf gestoßen, dass der letzte Parameter eine Zahl ist. Und dann mit ner Schleife von 0 bis 25 bin ich auf die 17 gestoßen.
    Bilder
    • Result.png

      11,06 kB, 319×378, 15 mal angesehen
    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 ganz herzlichen Dank ! Jau so kann man im BrowseForFolder Dialog auf "This PC" kommen.

    Ich hätte gedacht, die Antwort würde mein Problem lösen. Aber leider ist dem nicht so.

    Jetzt wirst du mir vermutlich gleich an die Gurgel springen, weil ich eigentlich weitergehende Anforderungen habe. Ich will nämlich nicht nur zu "This PC" springen, sondern zu meinem cell phone ... und dort in das Verzeichnis "DCIM".

    So sieht mein BrowseForFolder Window jetzt aus. (s. Anhang)

    Wie komme ich jetzt in den StartOrdner "This PC\GT-I9100\Phone\DCIM" ?

    Oder noch besser: wie kann ich denn abprüfen könnte, ob das cell phone überhaupt montiert ist- Das hängt nämlich nicht immer an meinem PC ... :)

    Ich würde also gern prüfen, ob es den o.a. Pfad überhaupt gibt. Und wenn der Pfad vorhanden ist, dann würde ich den BrowseForFolder Dialog gar nicht aufrufen wollen, sondern gleich das Verzeichnis verarbeiten.

    So, jetzt liegen die Karten auf dem Tisch ... Ich hoffe, es gibt eine Lösung für mein Problem ...

    LG
    Peter
    Bilder
    • s 2021-06-02 16-35-033.jpg

      12,99 kB, 314×313, 12 mal angesehen
    @Peter329

    Es gibt mehrere Möglichkeiten auf ein "portables Gerät" wie Handys zuzugreifen. Das eine wurde Dir ja schon genannt (Link zu dev.flauschig.ch). Du kannst auch direkt die entsprechenden Shell COM-Interfaces verwenden (Ohne zusaätzliche Verweise). Desweiteren gibt es die "Windows Portable Device"-COM-Interfaces (docs.microsoft.com/en-us/windo…/windows-portable-devices) die genau für solche Geräte, die per USB angeschlossen sind und keinen Laufwerksbuchstaben erhalten, verwendet werden kann. Für .NET gibt es z.B. dieses NuGet-Paket: nuget.org/packages/MediaDevices/1.8.0 Das NuGet-Paket hab ich nie verwendet. Mit den anderen Sachen habe ich schon mal programmiert.

    Peter329 schrieb:

    Oder noch besser: wie kann ich denn abprüfen könnte, ob das cell phone überhaupt montiert ist- Das hängt nämlich nicht immer an meinem PC ...
    "Windows Portable Device"-COM-Interface IPortableDeviceManager
    1. IPortableDeviceManager::RefreshDeviceList aufrufen
    2. IPortableDeviceManager::GetDevices aufrufen -> Pointer auf die GeräteIDs (Array)-> Pointer zu String = GeräteID. Schaut in etwas so aus "\\?\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#7&122e7c35&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}"
    3. IPortableDeviceManager::GetDeviceFriendlyName = Name des Gerätes
    4. IPortableDeviceManager::GetDeviceManufacturer = Hersteller des Gerätes
    5. IPortableDeviceManager::GetDeviceDescription = Beschreibung des Gerätes

    Dieser PC = ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}

    Direkt zum Pfad kommst also mit ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\GeräteID\Phone\DCIM.
    Mfg -Franky-

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

    @-Franky- hat dir ja im Prinzip die Lösung genannt.
    Also einfach mit If Directory.Exists("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\GeräteID\Phone\DCIM") Then prüfen ob dein Phone angeschlossen und betriebsbereit ist und dann entsprechend handeln.
    GeräteID musst du natürlich entsprechend anpassen
    Erst mal vielen Dank für eure Ratschläge. Ich hab mich mal ein bissl mit der Umsetzung befasst:

    @ThomasG82:

    Das mit dem Directory.Exists klappt bei mir nicht. Ich erhalte False auch wenn das Gerät angeschlossen ist. Der Windows Explorer zeigt das Gerät aber problemlos an.

    Ich frage mich, wo der kryptische lange String herkommt ... das sieht mir nach einer Windows GUID aus ...

    VB.NET-Quellcode

    1. ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}


    Ist denn gesichert, dass dieser String auch auf meinem PC richtig ist ? Und wie stabil ist dieser String, d.h. kann sich das möglicherweise schon beim nächsten Windows Update völlig ändern ?

    Fragen über Fragen ... aber in jedem Fall bringe ich das Dingens so nicht zum Laufen. Vielleicht hast du ja noch eine Idee.

    @-Franky-:

    -Franky- schrieb:

    IPortableDeviceManager::RefreshDeviceList aufrufen


    Die Schreibweise ist wohl C# ... die Klasse heißt wohl IPortableDeviceManager und die Methode RefreshDeviceList.

    Da müsste ich die Klasse doch erst mal instanzieren. So habe ich das (nach Suche im Internet) versucht:

    VB.NET-Quellcode

    1. Dim devMgr As PortableDeviceApiLib.PortableDeviceManagerClass =
    2. New PortableDeviceApiLib.PortableDeviceManagerClass


    Die Klasse PortableDeviceApiLib wird aber nicht gefunden. Fehlt da ein Imports ... ? Vielleicht bin ich da aber auch vollständig auf dem Holzweg ...

    Tja, auch da komme ich also nicht weiter. Ich hoffe, ihr habt genügend Geduld mit mir ... :)

    LG
    Peter

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

    Ok, ich glaube ich habe einen Doppelpunkt vergessen ;(
    Versuche mal über den Ausführen Dialog folgendes aus:

    Quellcode

    1. ​shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}

    Das ist ein Standardbefehl unter Windows. Sollte dich also immer auf Mein PC bringen
    @Peter329

    Peter329 schrieb:

    Das mit dem Directory.Exists klappt bei mir nicht. Ich erhalte False auch wenn das Gerät angeschlossen ist. Der Windows Explorer zeigt das Gerät aber problemlos an.

    Kann ja noch nicht funktionieren da Du ja für den ganzen Pfad noch die GeräteID einsetzen musst.

    Peter329 schrieb:

    frage mich, wo der kryptische lange String herkommt ... das sieht mir nach einer Windows GUID aus ...

    Das ist die CLSID für den virtuellen Ordner "Dieser PC".

    Peter329 schrieb:

    Die Klasse PortableDeviceApiLib wird aber nicht gefunden. Fehlt da ein Imports ... ?

    Keine Ahnung was Du da als Verweis gesetzt hast. Ich weis das es für WPD auch COM-Verweise gibt die man in .NET einbinden kann. Ich glaube mich aber erinnern zu können das es mit eiem Verweis ein Problem bei der Funktion GetDevices gab. What ever. Da ich kein Freund von irgendwelchen Fremdpaketen und Verweisen auf irgendwelchen COM-Interfaces bin, programmiere ich mir sowas immer selber (Der Code, der jetzt kommt, stammt aus einem über 5 Jahre alten Projekt).

    Zunächst: Erstelle eine Klasse mit dem Namen PortableDeviceManager mit folgendem Code
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Imports System.Text
    4. Imports System.Runtime.InteropServices
    5. Public Class PortableDeviceManager
    6. Implements IDisposable
    7. Private Const IID_IPortableDeviceManager As String = "A1567595-4C2F-4574-A6FA-ECEF917B9A40"
    8. Private Const CLSID_PortableDeviceManager As String = "0AF10CEC-2ECD-4B92-9581-34F6AE0637F3"
    9. Private Const S_OK As Integer = 0
    10. Public _ifc As IPortableDeviceManager
    11. Sub New()
    12. _ifc = DirectCast(Activator.CreateInstance(Type.GetTypeFromCLSID(New Guid(CLSID_PortableDeviceManager))), IPortableDeviceManager)
    13. End Sub
    14. #Region "Interface IPortableDeviceManager"
    15. ' https://msdn.microsoft.com/de-de/library/windows/desktop/dd388688(v=vs.85).aspx
    16. <ComImport>
    17. <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    18. <Guid(IID_IPortableDeviceManager)>
    19. Public Interface IPortableDeviceManager
    20. <PreserveSig> Function GetDevices(<[In], Out, MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.LPWStr, SizeParamIndex:=1)> ByVal pPnPDeviceIDs As String(),
    21. <[In], Out> ByRef pcPnPDeviceIDs As UInteger) As Integer
    22. <PreserveSig> Function RefreshDeviceList() As Integer
    23. <PreserveSig> Function GetDeviceFriendlyName(<[In], MarshalAs(UnmanagedType.LPWStr)> ByVal pszPnPDeviceID As String,
    24. <[In], Out, MarshalAs(UnmanagedType.LPWStr)> ByVal pDeviceFriendlyName As StringBuilder,
    25. <[In], Out> ByRef pcchDeviceFriendlyName As UInteger) As Integer
    26. <PreserveSig> Function GetDeviceDescription(<[In], MarshalAs(UnmanagedType.LPWStr)> ByVal pszPnPDeviceID As String,
    27. <[In], Out, MarshalAs(UnmanagedType.LPWStr)> ByVal pDeviceDescription As StringBuilder,
    28. <[In], Out> ByRef pcchDeviceDescription As UInteger) As Integer
    29. <PreserveSig> Function GetDeviceManufacturer(<[In], MarshalAs(UnmanagedType.LPWStr)> ByVal pszPnPDeviceID As String,
    30. <[In], Out, MarshalAs(UnmanagedType.LPWStr)> ByVal pDeviceManufacturer As StringBuilder,
    31. <[In], Out> ByRef pcchDeviceManufacturer As UInteger) As Integer
    32. <PreserveSig> Function GetDeviceProperty(<[In], MarshalAs(UnmanagedType.LPWStr)> ByVal pszPnPDeviceID As String,
    33. <[In], MarshalAs(UnmanagedType.LPWStr)> ByVal pszDevicePropertyName As String,
    34. <[In], Out, MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.ByValArray, SizeParamIndex:=1)> ByVal pData As Byte(),
    35. <[In], Out> ByRef pcbData As UInteger,
    36. <[In], Out> ByRef pdwType As UInteger) As Integer
    37. <PreserveSig> Function GetPrivateDevices(<[In], Out, MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.LPWStr, SizeParamIndex:=1)> ByVal pPnPDeviceIDs As String(),
    38. <[In], Out> ByRef pcPnPDeviceIDs As UInteger) As Integer
    39. End Interface
    40. #End Region
    41. #Region "Interface Helper"
    42. ' Retrieves the count of portable devices connected to the computer
    43. Public Function GetDeviceCount() As UInteger
    44. Dim iDevCount As UInteger
    45. Dim ret = _ifc.GetDevices(Nothing, iDevCount)
    46. If ret = S_OK Then
    47. Return iDevCount
    48. ElseIf ret <> S_OK Then
    49. Throw New COMException("GetDevices faild", ret)
    50. End If
    51. Return 0
    52. End Function
    53. ' Retrieves a list of portable devices connected to the computer
    54. Public Function GetDevices() As String()
    55. Dim iDevCount As UInteger = GetDeviceCount()
    56. If iDevCount > 0 Then
    57. Dim sPnpDeviceID = New String(CInt(iDevCount - 1)) {}
    58. Dim ret = _ifc.GetDevices(sPnpDeviceID, iDevCount)
    59. If ret = S_OK Then
    60. Return sPnpDeviceID
    61. ElseIf ret <> S_OK Then
    62. Throw New COMException("GetDevices faild", ret)
    63. End If
    64. Else
    65. Return New String(-1) {}
    66. End If
    67. Return Nothing
    68. End Function
    69. ' Refreshes the list of portable devices that are connected to the computer
    70. Public Function RefreshDeviceList() As Boolean
    71. Dim ret = _ifc.RefreshDeviceList
    72. If ret = S_OK Then
    73. Return True
    74. ElseIf ret <> S_OK Then
    75. Throw New COMException("RefreshDeviceList faild", ret)
    76. End If
    77. Return False
    78. End Function
    79. ' Retrieves the user-friendly name for the device
    80. Public Function GetDeviceFriendlyName(ByVal PnPDeviceID As String) As String
    81. Dim iCharCount As UInteger
    82. Dim ret = _ifc.GetDeviceFriendlyName(PnPDeviceID, Nothing, iCharCount)
    83. If ret = S_OK Then
    84. If iCharCount > 0 Then
    85. Dim sDeviceFriendlyName As StringBuilder = New StringBuilder(Char.MinValue, CInt(iCharCount - 1))
    86. ret = _ifc.GetDeviceFriendlyName(PnPDeviceID, sDeviceFriendlyName, iCharCount)
    87. If ret = S_OK Then
    88. Return sDeviceFriendlyName.ToString
    89. ElseIf ret <> S_OK Then
    90. Throw New COMException("GetDeviceFriendlyName faild", ret)
    91. End If
    92. End If
    93. ElseIf ret <> S_OK Then
    94. Throw New COMException("GetDeviceFriendlyName faild", ret)
    95. End If
    96. Return String.Empty
    97. End Function
    98. ' Retrieves the description of a device
    99. Public Function GetDeviceDescription(ByVal PnPDeviceID As String) As String
    100. Dim iCharCount As UInteger
    101. Dim ret = _ifc.GetDeviceDescription(PnPDeviceID, Nothing, iCharCount)
    102. If ret = S_OK Then
    103. If iCharCount > 0 Then
    104. Dim sDeviceDescription As StringBuilder = New StringBuilder(Char.MinValue, CInt(iCharCount - 1))
    105. ret = _ifc.GetDeviceDescription(PnPDeviceID, sDeviceDescription, iCharCount)
    106. If ret = S_OK Then
    107. Return sDeviceDescription.ToString
    108. ElseIf ret <> S_OK Then
    109. Throw New COMException("GetDeviceDescription faild", ret)
    110. End If
    111. End If
    112. ElseIf ret <> S_OK Then
    113. Throw New COMException("GetDeviceDescription faild", ret)
    114. End If
    115. Return String.Empty
    116. End Function
    117. ' Retrieves the name of the device manufacturer
    118. Public Function GetDeviceManufacturer(ByVal PnPDeviceID As String) As String
    119. Dim iCharCount As UInteger
    120. Dim ret = _ifc.GetDeviceManufacturer(PnPDeviceID, Nothing, iCharCount)
    121. If ret = S_OK Then
    122. If iCharCount > 0 Then
    123. Dim sDeviceDescription As StringBuilder = New StringBuilder(Char.MinValue, CInt(iCharCount - 1))
    124. ret = _ifc.GetDeviceManufacturer(PnPDeviceID, sDeviceDescription, iCharCount)
    125. If ret = S_OK Then
    126. Return sDeviceDescription.ToString
    127. ElseIf ret <> S_OK Then
    128. Throw New COMException("GetDeviceManufacturer faild", ret)
    129. End If
    130. End If
    131. ElseIf ret <> S_OK Then
    132. Throw New COMException("GetDeviceManufacturer faild", ret)
    133. End If
    134. Return String.Empty
    135. End Function
    136. ' Retrieves a property value stored by the device on the computer
    137. Public Function GetDeviceProperty(ByVal sPnpDeviceID As String, ByVal sDevicePropertyName As String) As String
    138. Dim iData As UInteger
    139. Dim iType As UInteger
    140. Dim ret = _ifc.GetDeviceProperty(sPnpDeviceID, sDevicePropertyName, Nothing, iData, iType)
    141. If ret = S_OK Then
    142. If iData > 0 Then
    143. Dim bData As Byte() = New Byte(CInt(iData - 1)) {}
    144. ret = _ifc.GetDeviceProperty(sPnpDeviceID, sDevicePropertyName, bData, iData, iType)
    145. If ret = S_OK Then
    146. ElseIf ret <> S_OK Then
    147. Throw New COMException("GetDeviceProperty faild", ret)
    148. End If
    149. End If
    150. ElseIf ret <> S_OK Then
    151. Throw New COMException("GetDeviceProperty faild", ret)
    152. End If
    153. Return String.Empty
    154. End Function
    155. ' Retrieves the count of private portable devices connected to the computer
    156. Public Function GetPrivateDeviceCount() As UInteger
    157. Dim iDevCount As UInteger
    158. Dim ret = _ifc.GetPrivateDevices(Nothing, iDevCount)
    159. If ret = S_OK Then
    160. Return iDevCount
    161. ElseIf ret <> S_OK Then
    162. Throw New COMException("GetPrivateDevices faild", ret)
    163. End If
    164. Return 0
    165. End Function
    166. ' Retrieves a list of private portable devices connected to the computer
    167. Public Function GetPrivateDevices() As String()
    168. Dim iDevCount As UInteger = GetPrivateDeviceCount()
    169. If iDevCount > 0 Then
    170. Dim sPnpDeviceID = New String(CInt(iDevCount - 1)) {}
    171. Dim ret = _ifc.GetPrivateDevices(sPnpDeviceID, iDevCount)
    172. If ret = S_OK Then
    173. Return sPnpDeviceID
    174. ElseIf ret <> S_OK Then
    175. Throw New COMException("GetPrivateDevices faild", ret)
    176. End If
    177. Else
    178. Return New String(-1) {}
    179. End If
    180. Return Nothing
    181. End Function
    182. #End Region
    183. #Region "IDisposable Support"
    184. Private disposedValue As Boolean
    185. Protected Overridable Sub Dispose(disposing As Boolean)
    186. If Not disposedValue Then
    187. If disposing Then
    188. ' TODO: verwalteten Zustand (verwaltete Objekte) entsorgen.
    189. End If
    190. If _ifc IsNot Nothing Then
    191. Marshal.ReleaseComObject(_ifc)
    192. _ifc = Nothing
    193. End If
    194. End If
    195. disposedValue = True
    196. End Sub
    197. Protected Overrides Sub Finalize()
    198. Dispose(False)
    199. MyBase.Finalize()
    200. End Sub
    201. Public Sub Dispose() Implements IDisposable.Dispose
    202. Dispose(True)
    203. GC.SuppressFinalize(Me)
    204. End Sub
    205. #End Region
    206. End Class


    Das ganze wird dann in der Form folgendermaßen aufgerufen
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim strPnpDevIDs As String()
    3. Dim strDeviceID As String
    4. Using IPDevManager As New PortableDeviceManager
    5. If IPDevManager.RefreshDeviceList = True Then
    6. Dim uiDevCount As UInteger = IPDevManager.GetDeviceCount()
    7. If uiDevCount > 0 Then
    8. strPnpDevIDs = IPDevManager.GetDevices
    9. For uiItem As UInteger = 0 To uiDevCount - 1UI
    10. strDeviceID = sPnpDevIDs(Convert.ToInt32(uiItem))
    11. Debug.Print("DeviceID = " & strDeviceID)
    12. Debug.Print("DeviceFriendlyName = " & IPDevManager.GetDeviceFriendlyName(strDeviceID))
    13. Debug.Print("DeviceManufacturer = " & IPDevManager.GetDeviceManufacturer(strDeviceID))
    14. Debug.Print("DeviceDescription = " & IPDevManager.GetDeviceDescription(strDeviceID))
    15. Next
    16. End If
    17. End If
    18. End Using
    19. End Sub


    Du kannst ja die entsprechende Infos in eine Structure (Array) schaufeln und den DeviceFriendlyName in eine ComboBox . Ist Dein Gerät in der Auflistung vorhanden, ist es angeschlossen. Es können ja auch mehrere "portable Geräte" angeschlossen sein. Dann wählst aus der Combobox Dein Gerät aus, holst Dir die passende DeviceID zum DeviceFriendlyName aus der Structure.
    Mfg -Franky-
    Wow ... das war natürlich SEHR nett von dir. Herzlichen Dank für den Code !

    Ich hab den Code übernommen ... die Klassendefinition ist Syntax fehlerfrei. Allerdings die Button1 Routine hat einen kleinen Compile Fehler:

    VB.NET-Quellcode

    1. strDeviceID = sPnpDevIDs(Convert.ToInt32(uiItem))


    Die Routine sPnpDevIDs wird nicht gefunden. So auf die Schnelle hab ich keine Ahnung, wo ich die herbekommen könnte. Vielleicht kannst du mir einen Hinweis geben.

    -Franky- schrieb:

    Kann ja noch nicht funktionieren da Du ja für den ganzen Pfad noch die GeräteID einsetzen musst.


    Ich habe natürlich meine GeräteId eingesetzt ... aber du hast schon recht: man weiß ja nie, was die Leute so treiben. :)

    VB.NET-Quellcode

    1. If Directory.Exists("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\GT-I9100\Phone\DCIM") Then
    2. lblMessage.Text = "OK"
    3. Else
    4. lblMessage.Text = "Not mounted."
    5. End If


    Die GeräteId habe ich aus dem Windows Explorer kopiert ... denn da wird das Gerät ja angezeigt. Das Ganze funktioniert also schlicht und ergreifend auf meinem PC nicht.

    -Franky- schrieb:

    Das ist die CLSID für den virtuellen Ordner "Dieser PC".


    Was ist den eine CLSID ... wie stabil ist sie ... und wie finde ich den Wert heraus, falls er sich einstmals ändern sollte ?

    Ich hoffe, ich bin nicht zu penetrant mit meiner Fragerei ... :)

    LG
    Peter

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

    Ob das direkt mit der CLSID funktioniert probiere ich gleich noch mal, sollte aber im englischen wie im deutschen System die gleiche sein, sie ist Windows weit gültig.Die CLSID ist kurz gesagt ein fester Wert aus der Registry für ein bestimmtes Kommando.
    Länge Erklärungen :
    Spoiler anzeigen
    ​Vorneweg die Info, dass CLSID für Class-ID steht und entsprechende Nummern in der Registrierungs-Datenbank eingetragen sind. Letztere enthält zahlreiche Einstellwerte von Windows und Drittanbieter-Software. Die CLSID-Codes sind Bezeichner für die COM-Objekte oder – einfacher gesagt – die Software-Komponenten des Betriebssystems.
    Dann sollte es doch möglich sein, diesen Wert aus der Registry auszulesen. Und damit auch in meinem Programm anzupassen, wenn sich der Wert irgendwann ändern sollte. Wo steht denn nun diese vermaledeite CLSID ...

    Offen gestanden bin ich ja froh, dass die Sache mit "This PC" nicht gar so einfach zu behandeln ist. Ich hatte schon befürchtet, dass ich irgend etwas völlig Triviales übersehen hätte ... :)

    LG
    Peter
    @Peter329

    Peter329 schrieb:

    Allerdings die Button1 Routine hat einen kleinen Compile Fehler

    Ups, kleiner Fehler meiner seits.

    Die Zeile sollte so aussehen

    VB.NET-Quellcode

    1. strDeviceID = strPnpDevIDs(Convert.ToInt32(uiItem))


    Peter329 schrieb:

    Ich habe natürlich meine GeräteId eingesetzt

    Nö, hast Du nicht. Du hast den FriendyName Deines Handys eingesetzt. Nicht die GeräteID des Handys. Die GeräteID beginnt mit \\?\
    Mfg -Franky-
    Jau ... der Compiler Fehler ist jetzt wech ... nachher test ich das dann !

    -Franky- schrieb:

    Nö, hast Du nicht. Du hast den FriendyName Deines Handys eingesetzt. Nicht die GeräteID des Handys. Die GeräteID beginnt mit \\?\


    Das verstehe ich jetzt ... der Explorer zeigt mir also den FriendyName an ... Und wo bekomme ich jetzt die GeräteId her ?

    LG
    Peter
    @Peter329

    Peter329 schrieb:

    Das verstehe ich jetzt ... der Explorer zeigt mir also den FriendyName an ... Und wo bekomme ich jetzt die GeräteId her ?

    Die GeräteID steht in strDeviceID.

    Wie geschrieben: Bei mir schaut der Pfad so aus: ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#7&122e7c35&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\Phone\DCIM
    Mfg -Franky-
    Ok ... jetzt hab ich das geschnallt.

    Dein Programm funktioniert hervorragend. Einfach genial !

    Leider klappt aber mein Directory Test auch mit der DeviceID immer noch nicht. So habe ich das eingebaut:

    VB.NET-Quellcode

    1. For uiItem As UInteger = 0 To uiDevCount - 1UI
    2. strDeviceID = strPnpDevIDs(Convert.ToInt32(uiItem))
    3. Debug.Print("DeviceID = " & strDeviceID)
    4. Debug.Print("DeviceFriendlyName = " & IPDevManager.GetDeviceFriendlyName(strDeviceID))
    5. Debug.Print("DeviceManufacturer = " & IPDevManager.GetDeviceManufacturer(strDeviceID))
    6. Debug.Print("DeviceDescription = " & IPDevManager.GetDeviceDescription(strDeviceID))
    7. If IPDevManager.GetDeviceFriendlyName(strDeviceID) = "GT-I9100" Then
    8. Dim DevPath = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\" & strDeviceID & "\Phone\DCIM"
    9. Debug.Print("DevicePath = " & DevPath)
    10. Debug.Print("Mounted = " & Directory.Exists(DevPath).ToString)
    11. End If
    12. Next


    Und das ist die Ausgabe:

    Quellcode

    1. DeviceID = \\?\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#7&2d74280c&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}
    2. DeviceFriendlyName = GT-I9100
    3. DeviceManufacturer = SAMSUNG Electronics Co. Ltd.
    4. DeviceDescription = GT-I9100
    5. DevicePath = ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#7&2d74280c&0&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\Phone\DCIM
    6. Mounted = False


    Hast du eine Idee wie und wo ich nach dem Fehler suchen könnte ? Vielleicht habe ich ja eine andere CLSID ? Nur wie kann ich das jetzt wieder abprüfen ...

    Ich hoffe, du hast noch ein wenig Geduld mit mir ... :)

    LG
    Peter

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