none
How do I locate the Download folder on my mobile phone RRS feed

  • Question

  • When I connect my mobile phone via USB, explorer shows it as a device? with relevant folders

    In VB code (need I say that?) how do I detect the phone & its folders so I can have my app (written in VB) create a file in Downloads

    If you don't have the answer please do not suggest links, as 99% of the time I look at them & find no relevance or are too complex or vague to modify to suit my needs.

    Thanks for any assistance

    Wednesday, May 20, 2020 6:02 AM

Answers

  • The flag=16 in CopyHere should suppress the confirmation dialog box, but it doesn't...
    It only works with IFileOperation

    So, this works for me with IFileOperation and FOF_NOCONFIRMATION flag,

    but you must check sFolderPathFull to see if it contains a SID like on my phone, that I have to remove

    ("SID-{10001,,5412716544}")

    If it is different, you will have to change the Regex or it won't work...

    =>

    Dim oShell As Shell32.Shell = New Shell32.Shell()
    Dim oFolderMyComputer As Shell32.Folder = oShell.[NameSpace](Shell32.ShellSpecialFolderConstants.ssfDRIVES)
    
    Dim sSourceFile As String = "e:\test.jpg"
    Dim fi As IO.FileInfo = New IO.FileInfo(sSourceFile)
    Dim sFileName As String = fi.Name
    Dim sDrive As String = IO.Path.GetPathRoot(fi.FullName)
    
    Dim hDLL As IntPtr = LoadLibrary("C:\WINDOWS\system32\wpdshext.dll")
    Dim sbStringWPD As System.Text.StringBuilder = New System.Text.StringBuilder(260)
    LoadString(hDLL, 347, sbStringWPD, sbStringWPD.Capacity)
    
    Dim oFolderItemWPD As Shell32.FolderItem2 = Nothing
    For Each oFolderItem As Shell32.FolderItem2 In oFolderMyComputer.Items()
        Dim sItemName As String = oFolderItem.Name
        Dim sItemType As String = oFolderItem.Type
        Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
        If (sItemType = sbStringWPD.ToString()) Then
            oFolderItemWPD = oFolderItem
            Exit For
        End If
        ' Name : Archos 40 Helium - Type : Lecteur multimédia portable
    Next
    If (oFolderItemWPD IsNot Nothing) Then
        MessageBox.Show("Portable Device found : " + oFolderItemWPD.Name, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
        Dim oFolderWPD As Shell32.Folder = CType(oFolderItemWPD.GetFolder(), Shell32.Folder)
        Dim oFolderDownload As Shell32.Folder = Nothing
        'RecurseFolder(oFolderWPD, "Download", "Mémoire de stockage interne", oFolderDownload)
        RecurseFolder(oFolderWPD, "Download", "Phone", oFolderDownload)
        ' RecurseFolder(oFolderWPD, "Download", Nothing, oFolderDownload)
        If (oFolderDownload IsNot Nothing) Then
            Dim pShellItemSource As IShellItem = Nothing, pShellItemDest As IShellItem = Nothing
            Dim hr As HRESULT = SHCreateItemFromParsingName(sSourceFile, IntPtr.Zero, GetType(IShellItem).GUID, pShellItemSource)
    
            Dim sFolderPathFull As String = oFolderDownload.ParentFolder.ParseName(oFolderDownload.Title).Path
            ' ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_0e79&pid_52c2#908165c02an9577#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\SID-{10001,,5412716544}\{0000000F-0001-0001-0000-000000000000}\{00000760-0001-0001-0000-000000000000}
            ' Remove Internal Storage ID
            Dim sFolderPath As String = System.Text.RegularExpressions.Regex.Replace(sFolderPathFull, "SID.*?\\", "")
            hr = SHCreateItemFromParsingName(sFolderPath, IntPtr.Zero, GetType(IShellItem).GUID, pShellItemDest)
    
            Dim pfo As IFileOperation = CType(Activator.CreateInstance(FileOperationType), IFileOperation)
            ' Suppress confirmation Dialog Box
            hr = pfo.SetOperationFlags(FILEOP_FLAGS.FOF_NOCONFIRMATION)
            hr = pfo.CopyItem(pShellItemSource, pShellItemDest, Nothing, IntPtr.Zero)
            If (hr = HRESULT.S_OK) Then
                hr = pfo.PerformOperations()
            End If
            Marshal.ReleaseComObject(pfo)
        Else
            MessageBox.Show("Download folder not found on " + oFolderItemWPD.Name, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If
    End If
    
    Private Sub RecurseFolder(oFolderParent As Shell32.Folder, sFolderToFind As String, sParentFolderToFind As String, ByRef oFolderToFind As Shell32.Folder)
        For Each oFolderItem As Shell32.FolderItem In oFolderParent.Items()
            Dim sItemName As String = oFolderItem.Name
            Dim sItemType As String = oFolderItem.Type
            ' For test
            Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
            If (sItemName = sFolderToFind) Then
                Dim oFolderItemParent As Shell32.Folder = CType(oFolderItem.Parent, Shell32.Folder)
                If (oFolderItemParent.Title = sParentFolderToFind Or sParentFolderToFind = Nothing) Then
                    oFolderToFind = CType(oFolderItem.GetFolder(), Shell32.Folder)
                    Return
                End If
            End If
            If (oFolderItem.IsFolder) Then
                RecurseFolder(CType(oFolderItem.GetFolder(), Shell32.Folder), sFolderToFind, sParentFolderToFind, oFolderToFind)
            End If
        Next
    End Sub

    Declarations :

        Public Enum HRESULT As Integer
            S_OK = 0
            S_FALSE = 1
            E_NOINTERFACE = &H80004002
            E_NOTIMPL = &H80004001
            E_FAIL = &H80004005
            E_INVALIDARG = &H80070057
            E_UNEXPECTED = &H8000FFFF
            E_OUTOFMEMORY = &H8007000E
        End Enum
    
        <ComImport()> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> <Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")>
        Public Interface IShellItem
            Function BindToHandler(ByVal pbc As IntPtr, ByRef bhid As Guid, ByRef riid As Guid, ByRef ppv As IntPtr) As HRESULT
            Function GetParent(ByRef ppsi As IShellItem) As HRESULT
            Function GetDisplayName(ByVal sigdnName As SIGDN, ByRef ppszName As System.Text.StringBuilder) As HRESULT
            Function GetAttributes(ByVal sfgaoMask As UInteger, ByRef psfgaoAttribs As UInteger) As HRESULT
            Function Compare(ByVal psi As IShellItem, ByVal hint As UInteger, ByRef piOrder As Integer) As HRESULT
        End Interface
    
        Public Enum SIGDN As Integer
            SIGDN_NORMALDISPLAY = &H0
            SIGDN_PARENTRELATIVEPARSING = &H80018001
            SIGDN_DESKTOPABSOLUTEPARSING = &H80028000
            SIGDN_PARENTRELATIVEEDITING = &H80031001
            SIGDN_DESKTOPABSOLUTEEDITING = &H8004C000
            SIGDN_FILESYSPATH = &H80058000
            SIGDN_URL = &H80068000
            SIGDN_PARENTRELATIVEFORADDRESSBAR = &H8007C001
            SIGDN_PARENTRELATIVE = &H80080001
        End Enum
    
        <ComImport()> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> <Guid("947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8")>
        Friend Interface IFileOperation
            Function Advise(ByVal pfops As IntPtr, ByRef pdwCookie As UInteger) As HRESULT
            Function Unadvise(ByVal dwCookie As UInteger) As HRESULT
            Function SetOperationFlags(ByVal dwOperationFlags As FILEOP_FLAGS) As HRESULT
            Function SetProgressMessage(<MarshalAs(UnmanagedType.LPWStr)> ByVal pszMessage As String) As HRESULT
            Function SetProgressDialog(<MarshalAs(UnmanagedType.[Interface])> ByVal popd As Object) As HRESULT
            Function SetProperties(<MarshalAs(UnmanagedType.[Interface])> ByVal pproparray As Object) As HRESULT
            Function SetOwnerWindow(ByVal hwndParent As UInteger) As HRESULT
            Function ApplyPropertiesToItem(ByVal psiItem As IShellItem) As HRESULT
            Function ApplyPropertiesToItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object) As HRESULT
            Function RenameItem(ByVal psiItem As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String, ByVal pfopsItem As IntPtr) As HRESULT
            Function RenameItems(<MarshalAs(UnmanagedType.[Interface])> ByVal pUnkItems As Object, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String) As HRESULT
            <PreserveSig()>
            Function MoveItem(ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function MoveItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object, ByVal psiDestinationFolder As IShellItem) As HRESULT
            <PreserveSig()>
            Function CopyItem(ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszCopyName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function CopyItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object, ByVal psiDestinationFolder As IShellItem) As HRESULT
            Function DeleteItem(ByVal psiItem As IShellItem, ByVal pfopsItem As IntPtr) As HRESULT
            Function DeleteItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object) As HRESULT
            Function NewItem(ByVal psiDestinationFolder As IShellItem, ByVal dwFileAttributes As System.IO.FileAttributes, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszName As String,
                             <MarshalAs(UnmanagedType.LPWStr)> ByVal pszTemplateName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function PerformOperations() As HRESULT
            Function GetAnyOperationsAborted() As Boolean
        End Interface
    
        <Flags>
        Public Enum FILEOP_FLAGS
            FOF_MULTIDESTFILES = &H1
            FOF_CONFIRMMOUSE = &H2
            FOF_SILENT = &H4
            FOF_RENAMEONCOLLISION = &H8
            FOF_NOCONFIRMATION = &H10
            FOF_WANTMAPPINGHANDLE = &H20
            FOF_ALLOWUNDO = &H40
            FOF_FILESONLY = &H80
            FOF_SIMPLEPROGRESS = &H100
            FOF_NOCONFIRMMKDIR = &H200
            FOF_NOERRORUI = &H400
            FOF_NOCOPYSECURITYATTRIBS = &H800
            FOF_NORECURSION = &H1000
            FOF_NO_CONNECTED_ELEMENTS = &H2000
            FOF_WANTNUKEWARNING = &H4000
            FOF_NORECURSEREPARSE = &H8000
            FOF_NO_UI = (FOF_SILENT Or FOF_NOCONFIRMATION Or FOF_NOERRORUI Or FOF_NOCONFIRMMKDIR) ' don't display any UI at all
            FOFX_NOSKIPJUNCTIONS = &H10000
            FOFX_PREFERHARDLINK = &H20000
            FOFX_SHOWELEVATIONPROMPT = &H40000
            FOFX_EARLYFAILURE = &H100000
            FOFX_PRESERVEFILEEXTENSIONS = &H200000
            FOFX_KEEPNEWERFILE = &H400000
            FOFX_NOCOPYHOOKS = &H800000
            FOFX_NOMINIMIZEBOX = &H1000000
            FOFX_MOVEACLSACROSSVOLUMES = &H2000000
            FOFX_DONTDISPLAYSOURCEPATH = &H4000000
            FOFX_DONTDISPLAYDESTPATH = &H8000000
        End Enum
    
        Public Const SFGAO_DROPTARGET = &H100L 'Objects are drop target
        Public Const SFGAO_FOLDER = &H20000000L 'Support BindToObject(IID_IShellFolder)
        Public Const SFGAO_FILESYSTEM = &H40000000L 'Is a win32 file system Object (file/folder/root)
        Public Const SFGAO_STREAM = &H400000L 'Supports BindToObject(IID_IStream)
        Public Const SFGAO_STORAGE = &H8L 'supports BindToObject(IID_IStorage)
        Public Const SFGAO_READONLY = &H40000L ' Read-only
    
        Public Const DROPEFFECT_COPY = (1)
        Public Const DROPEFFECT_MOVE = (2)
        Public Const SFGAO_CANCOPY = DROPEFFECT_COPY 'Objects can be copied    (0x1)
        Public Const SFGAO_CANMOVE = DROPEFFECT_MOVE ' Objects can be moved     (0x2)
    
        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function LoadString(ByVal hInstance As IntPtr, ByVal uID As Integer, ByVal lpBuffer As System.Text.StringBuilder, ByVal cchBufferMax As Integer) As Integer
        End Function
    
        <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Private Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
        End Function
    
        <DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function SHCreateItemFromParsingName(ByVal pszPath As String, ByVal pbc As IntPtr, <[In], MarshalAs(UnmanagedType.LPStruct)> ByVal riid As Guid, <Out> ByRef ppv As IShellItem) As HRESULT
        End Function
    
        Public Shared CLSID_FileOperation As Guid = New Guid("3ad05575-8857-4850-9277-11b85bdb8e09")
        Public Shared FileOperationType As Type = Type.GetTypeFromCLSID(CLSID_FileOperation)

    • Marked as answer by x38class Friday, May 29, 2020 5:42 AM
    Wednesday, May 27, 2020 11:20 AM

All replies

  • Hi x38class,

    Thank you for posting here.

    According to your question, I have some questions to confirm with you.

    What's the type of your application? WPF? Xamarin.Forms?

    Could you provide more details about your qustion or some related code here? It will help us to analyze your problem and make a test.

    We are waiting for your uppdate.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, May 22, 2020 2:54 AM
    Moderator
  • I dont know how to make this more simple!

    It's a Windows Forms application, as far as I know you cant get anything simpler than that.

    Lets start again, I connect my phone to computer, Windows Explorer shows Mobile Phone & its folders.

    What is the VB code to show same, Simples

    Friday, May 22, 2020 5:16 AM
  • Hi x38class,

    Thanks for your feedback.

    We’re doing research on this issue. It might take some time before we get back to you.

    Thank you for your patience。

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, May 22, 2020 9:23 AM
    Moderator
  • A way is with SHBrowseForFolder (root = shell:::{35786D3C-B075-49b9-88DD-029876E11C01})

    and IFileOperation.CopyItem (P/Invoke)

    I tested by copying a "test.jpg" file to Download folder on my "Archos" portable (french OS) :

    Friday, May 22, 2020 9:55 AM
  • Thanks Castorix31 for your interest & reply.

    Obviously you have been able to re-create what I am looking for, however after looking at your links, it is obvious I do not have the expertise to include/modify the code shown to resolve my issue.

    Is it possible for you to post your code verbatim, thnaks

    Saturday, May 23, 2020 4:04 AM
  • There are other methods like PortableDeviceApi, but I did not test this one

    Test with SHBrowseForFolder and IFileOperation.CopyItem =>

    Dim sSourceFile = "E:\test.jpg"
    Dim sDestFolder = "Download" 'if folder name needs to be tested
    
    Dim hr As HRESULT = HRESULT.E_FAIL
    Dim pidlRet As IntPtr = IntPtr.Zero
    Dim bi As BROWSEINFO = New BROWSEINFO()
    bi.hwndOwner = Handle
    bi.lpszTitle = "Title"
    bi.ulFlags = BIF_USENEWUI Or BIF_BROWSEINCLUDEFILES
    Dim pidlRoot As IntPtr = IntPtr.Zero
    Dim nrgflnOut As UInteger = 0
    hr = SHILCreateFromPath("shell:::{35786D3C-B075-49b9-88DD-029876E11C01}", pidlRoot, nrgflnOut)
    '  hr = SHILCreateFromPath("E:\temp", pidlRoot, nrgflnOut)
    If (hr = HRESULT.S_OK) Then
        bi.pidlRoot = pidlRoot
        pidlRet = SHBrowseForFolder(bi)
        If (pidlRet <> IntPtr.Zero) Then
    
            'Dim sSBPath As System.Text.StringBuilder = New System.Text.StringBuilder(260)
            'Dim bRet As Boolean = SHGetPathFromIDList(pidlRet, sSBPath)
    
            Dim pShellItemSource As IShellItem = Nothing, pShellItemDest As IShellItem = Nothing
            hr = SHCreateItemFromParsingName(sSourceFile, IntPtr.Zero, GetType(IShellItem).GUID, pShellItemSource)
            If (hr = HRESULT.S_OK) Then
                hr = SHCreateItemFromIDList(pidlRet, GetType(IShellItem).GUID, pShellItemDest)
                If (hr = HRESULT.S_OK) Then
                    'You can test folder name
                    Dim sSBDisplayName As System.Text.StringBuilder = New System.Text.StringBuilder(260)
                    pShellItemDest.GetDisplayName(SIGDN.SIGDN_NORMALDISPLAY, sSBDisplayName)
                    'If (sSBDisplayName.ToString() = sDestFolder) Then
                    Dim bFolderOK As Boolean = False
                    Dim nAttributes As UInteger = 0
                    hr = pShellItemDest.GetAttributes(SFGAO_FOLDER Or SFGAO_FILESYSTEM Or SFGAO_STREAM Or SFGAO_STORAGE Or SFGAO_READONLY Or SFGAO_CANCOPY Or SFGAO_CANMOVE, nAttributes)
                    'If (nAttributes And SFGAO_FOLDER) = SFGAO_FOLDER 'And (nAttributes And SFGAO_FILESYSTEM) = SFGAO_FILESYSTEM And (nAttributes And SFGAO_STREAM) <> SFGAO_STREAM Then
                    If (nAttributes And SFGAO_FOLDER) = SFGAO_FOLDER And (nAttributes And SFGAO_STORAGE) = SFGAO_STORAGE And (nAttributes And SFGAO_CANCOPY) = SFGAO_CANCOPY And (nAttributes And SFGAO_CANMOVE) = SFGAO_CANMOVE Then 'And (nAttributes And SFGAO_FILESYSTEM) = SFGAO_FILESYSTEM And (nAttributes And SFGAO_STREAM) <> SFGAO_STREAM Then
                        bFolderOK = True
                    Else
                        bFolderOK = False
                    End If
                    If (bFolderOK) Then
                        Dim pfo As IFileOperation = CType(Activator.CreateInstance(FileOperationType), IFileOperation)
                        If (pfo IsNot Nothing) Then
                            hr = pfo.CopyItem(pShellItemSource, pShellItemDest, Nothing, IntPtr.Zero)
                            If (hr = HRESULT.S_OK) Then
                                hr = pfo.PerformOperations()
                            End If
                            Marshal.ReleaseComObject(pfo)
                        End If
                    Else
                        MessageBox.Show("Destination must be a valid directory", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                    End If
                End If
            End If
        End If
    End If

    Declarations :

        Public Enum HRESULT As Integer
            S_OK = 0
            S_FALSE = 1
            E_NOINTERFACE = &H80004002
            E_NOTIMPL = &H80004001
            E_FAIL = &H80004005
            E_INVALIDARG = &H80070057
            E_UNEXPECTED = &H8000FFFF
            E_OUTOFMEMORY = &H8007000E
        End Enum
    
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
        Public Class BROWSEINFO
            Public hwndOwner As IntPtr
            Public pidlRoot As IntPtr
            Public pszDisplayName As IntPtr
            Public lpszTitle As String
            Public ulFlags As Integer
            Public lpfn As BrowseCallbackProc
            Public lParam As IntPtr
            Public iImage As Integer
        End Class
    
        Public Delegate Function BrowseCallbackProc(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal lParam As IntPtr, ByVal lpData As IntPtr) As Integer
    
        <DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function SHBrowseForFolder(<[In]> ByVal lpbi As BROWSEINFO) As IntPtr
        End Function
    
        Public Const BIF_RETURNONLYFSDIRS As Integer = &H1
        Public Const BIF_DONTGOBELOWDOMAIN As Integer = &H2
        Public Const BIF_STATUSTEXT As Integer = &H4
        Public Const BIF_RETURNFSANCESTORS As Integer = &H8
        Public Const BIF_EDITBOX As Integer = &H10
        Public Const BIF_VALIDATE As Integer = &H20
        Public Const BIF_NEWDIALOGSTYLE As Integer = &H40
        Public Const BIF_USENEWUI As Integer = (BIF_NEWDIALOGSTYLE Or BIF_EDITBOX)
        Public Const BIF_BROWSEINCLUDEURLS As Integer = &H80
        Public Const BIF_UAHINT As Integer = &H100
        Public Const BIF_NONEWFOLDERBUTTON As Integer = &H200
        Public Const BIF_NOTRANSLATETARGETS As Integer = &H400
        Public Const BIF_BROWSEFORCOMPUTER As Integer = &H1000
        Public Const BIF_BROWSEFORPRINTER As Integer = &H2000
        Public Const BIF_BROWSEINCLUDEFILES As Integer = &H4000
        Public Const BIF_SHAREABLE As Integer = &H8000
        Public Const BIF_BROWSEFILEJUNCTIONS As Integer = &H10000
    
        <ComImport()> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> <Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")>
        Public Interface IShellItem
            Function BindToHandler(ByVal pbc As IntPtr, ByRef bhid As Guid, ByRef riid As Guid, ByRef ppv As IntPtr) As HRESULT
            Function GetParent(ByRef ppsi As IShellItem) As HRESULT
            Function GetDisplayName(ByVal sigdnName As SIGDN, ByRef ppszName As System.Text.StringBuilder) As HRESULT
            Function GetAttributes(ByVal sfgaoMask As UInteger, ByRef psfgaoAttribs As UInteger) As HRESULT
            Function Compare(ByVal psi As IShellItem, ByVal hint As UInteger, ByRef piOrder As Integer) As HRESULT
        End Interface
    
        Public Enum SIGDN As Integer
            SIGDN_NORMALDISPLAY = &H0
            SIGDN_PARENTRELATIVEPARSING = &H80018001
            SIGDN_DESKTOPABSOLUTEPARSING = &H80028000
            SIGDN_PARENTRELATIVEEDITING = &H80031001
            SIGDN_DESKTOPABSOLUTEEDITING = &H8004C000
            SIGDN_FILESYSPATH = &H80058000
            SIGDN_URL = &H80068000
            SIGDN_PARENTRELATIVEFORADDRESSBAR = &H8007C001
            SIGDN_PARENTRELATIVE = &H80080001
        End Enum
    
    
        <ComImport()> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> <Guid("947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8")>
        Friend Interface IFileOperation
            Function Advise(ByVal pfops As IntPtr, ByRef pdwCookie As UInteger) As HRESULT
            Function Unadvise(ByVal dwCookie As UInteger) As HRESULT
            Function SetOperationFlags(ByVal dwOperationFlags As FILEOP_FLAGS) As HRESULT
            Function SetProgressMessage(<MarshalAs(UnmanagedType.LPWStr)> ByVal pszMessage As String) As HRESULT
            Function SetProgressDialog(<MarshalAs(UnmanagedType.[Interface])> ByVal popd As Object) As HRESULT
            Function SetProperties(<MarshalAs(UnmanagedType.[Interface])> ByVal pproparray As Object) As HRESULT
            Function SetOwnerWindow(ByVal hwndParent As UInteger) As HRESULT
            Function ApplyPropertiesToItem(ByVal psiItem As IShellItem) As HRESULT
            Function ApplyPropertiesToItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object) As HRESULT
            Function RenameItem(ByVal psiItem As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String, ByVal pfopsItem As IntPtr) As HRESULT
            Function RenameItems(<MarshalAs(UnmanagedType.[Interface])> ByVal pUnkItems As Object, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String) As HRESULT
            <PreserveSig()>
            Function MoveItem(ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function MoveItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object, ByVal psiDestinationFolder As IShellItem) As HRESULT
            <PreserveSig()>
            Function CopyItem(ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszCopyName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function CopyItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object, ByVal psiDestinationFolder As IShellItem) As HRESULT
            Function DeleteItem(ByVal psiItem As IShellItem, ByVal pfopsItem As IntPtr) As HRESULT
            Function DeleteItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object) As HRESULT
            Function NewItem(ByVal psiDestinationFolder As IShellItem, ByVal dwFileAttributes As System.IO.FileAttributes, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszName As String,
                             <MarshalAs(UnmanagedType.LPWStr)> ByVal pszTemplateName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function PerformOperations() As HRESULT
            Function GetAnyOperationsAborted() As Boolean
        End Interface
    
        <Flags>
        Public Enum FILEOP_FLAGS
            FOF_MULTIDESTFILES = &H1
            FOF_CONFIRMMOUSE = &H2
            FOF_SILENT = &H4
            FOF_RENAMEONCOLLISION = &H8
            FOF_NOCONFIRMATION = &H10
            FOF_WANTMAPPINGHANDLE = &H20
            FOF_ALLOWUNDO = &H40
            FOF_FILESONLY = &H80
            FOF_SIMPLEPROGRESS = &H100
            FOF_NOCONFIRMMKDIR = &H200
            FOF_NOERRORUI = &H400
            FOF_NOCOPYSECURITYATTRIBS = &H800
            FOF_NORECURSION = &H1000
            FOF_NO_CONNECTED_ELEMENTS = &H2000
            FOF_WANTNUKEWARNING = &H4000
            FOF_NORECURSEREPARSE = &H8000
            FOFX_NOSKIPJUNCTIONS = &H10000
            FOFX_PREFERHARDLINK = &H20000
            FOFX_SHOWELEVATIONPROMPT = &H40000
            FOFX_EARLYFAILURE = &H100000
            FOFX_PRESERVEFILEEXTENSIONS = &H200000
            FOFX_KEEPNEWERFILE = &H400000
            FOFX_NOCOPYHOOKS = &H800000
            FOFX_NOMINIMIZEBOX = &H1000000
            FOFX_MOVEACLSACROSSVOLUMES = &H2000000
            FOFX_DONTDISPLAYSOURCEPATH = &H4000000
            FOFX_DONTDISPLAYDESTPATH = &H8000000
        End Enum
    
        Public Const SFGAO_DROPTARGET = &H100L 'Objects are drop target
        Public Const SFGAO_FOLDER = &H20000000L 'Support BindToObject(IID_IShellFolder)
        Public Const SFGAO_FILESYSTEM = &H40000000L 'Is a win32 file system Object (file/folder/root)
        Public Const SFGAO_STREAM = &H400000L 'Supports BindToObject(IID_IStream)
        Public Const SFGAO_STORAGE = &H8L 'supports BindToObject(IID_IStorage)
        Public Const SFGAO_READONLY = &H40000L ' Read-only
    
        Public Const DROPEFFECT_COPY = (1)
        Public Const DROPEFFECT_MOVE = (2)
        Public Const SFGAO_CANCOPY = DROPEFFECT_COPY 'Objects can be copied    (0x1)
        Public Const SFGAO_CANMOVE = DROPEFFECT_MOVE ' Objects can be moved     (0x2)
    
        <DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function SHILCreateFromPath(<MarshalAs(UnmanagedType.LPWStr)> ByVal pszPath As String, ByRef ppIdl As IntPtr, ByRef rgflnOut As UInteger) As HRESULT
        End Function
    
        <DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function SHCreateItemFromParsingName(ByVal pszPath As String, ByVal pbc As IntPtr, <[In], MarshalAs(UnmanagedType.LPStruct)> ByVal riid As Guid, <Out> ByRef ppv As IShellItem) As HRESULT
        End Function
    
        <DllImport("Shell32", SetLastError:=False, CharSet:=CharSet.Unicode)>
        Public Shared Function SHCreateItemFromIDList(ByVal pidl As IntPtr, <[In], MarshalAs(UnmanagedType.LPStruct)> ByVal riid As Guid, <Out> ByRef ppv As IShellItem) As HRESULT
        End Function
    
        <DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function SHGetPathFromIDList(ByVal pidl As IntPtr, ByVal pszPath As System.Text.StringBuilder) As Boolean
        End Function
    
    
        Public Shared CLSID_FileOperation As Guid = New Guid("3ad05575-8857-4850-9277-11b85bdb8e09")
        Public Shared FileOperationType As Type = Type.GetTypeFromCLSID(CLSID_FileOperation)

    Saturday, May 23, 2020 7:50 AM
  • Thanks for your code which I have successfully implemented, however

    I was not expecting to duplicate windows explorer, (I can already use Windows Exporer to do this) maybe I did not make it very clear, regardless of what code is used to satisfy my app, what I was intending to do was something like:

    FileCopy("E:\test.jpg", "MobilePhone\Download\test.jpg") within the app itself, where "MobilePhone\Download" would be detected by code first

    If there is no answer to this you can give, I am happy to mark your reply as an answer

    Sunday, May 24, 2020 5:30 AM
  • One of the other methods is with the Shell
    I read the localized string for WPD from wpdshext.dll on my Windows 10 french OS, but not sure if it will work on other OS
    Otherwise, you will have to hardcode this string (sbStringWPD.ToString() in this test) to identify the portable device ("Lecteur multimédia portable" in french)

    There is also a "Memory sub-directory" on my mobile phone ( "Mémoire de stockage interne" in french) that I had to test (oFolderMemory) : maybe it doesn't exist on other phones... (you will have to remove this test if it doesn't exist) 

    (I added Console.WriteLine or MessageBox.Show for debugging)

    =>

    ' Add reference to : Microsoft Shell Controls and Automation
    
    Dim oShell As Shell32.Shell = New Shell32.Shell()
    Dim oFolderMyComputer As Shell32.Folder = oShell.[NameSpace](Shell32.ShellSpecialFolderConstants.ssfDRIVES)
    Dim sFile As String = "e:\test.jpg"
    Dim fi As IO.FileInfo = New IO.FileInfo(sFile)
    Dim sFileName As String = fi.Name
    Dim sDrive As String = IO.Path.GetPathRoot(fi.FullName)  
    
    ' Try to find "Lecteur multimédia portable" (french) or in other language
    Dim hDLL As IntPtr = LoadLibrary("C:\WINDOWS\system32\wpdshext.dll")
    Dim sbStringWPD As System.Text.StringBuilder = New System.Text.StringBuilder(260)
    LoadString(hDLL, 347, sbStringWPD, sbStringWPD.Capacity)
    
    Dim oFolderItemWPD As Shell32.FolderItem2 = Nothing
    For Each oFolderItem As Shell32.FolderItem2 In oFolderMyComputer.Items()
        Dim sItemName As String = oFolderItem.Name
        Dim sItemType As String = oFolderItem.Type
        Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
        If (sItemType = sbStringWPD.ToString()) Then
            oFolderItemWPD = oFolderItem
            Exit For
        End If
        ' Name : Archos 40 Helium - Type : Lecteur multimédia portable
    Next
    If (oFolderItemWPD IsNot Nothing) Then
        MessageBox.Show("Portable Device found : " + oFolderItemWPD.Name, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
        Dim oFolderWPD As Shell32.Folder = CType(oFolderItemWPD.GetFolder(), Shell32.Folder)
        Dim oFolderMemory As Shell32.Folder = Nothing
        For Each oFolderItem As Shell32.FolderItem2 In oFolderWPD.Items()
            Dim sItemName As String = oFolderItem.Name
            Dim sItemType As String = oFolderItem.Type
            Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
            oFolderMemory = CType(oFolderItem.GetFolder(), Shell32.Folder)
            ' Name : Mémoire de stockage interne - Type : Hiérarchique, générique
        Next
    
        Dim oFolderDownload As Shell32.Folder = Nothing
        If (oFolderMemory IsNot Nothing) Then
            For Each oFolderItem As Shell32.FolderItem2 In oFolderMemory.Items()
                Dim sItemName As String = oFolderItem.Name
                Dim sItemType As String = oFolderItem.Type
                Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
                If (sItemName = "Download") Then
                    oFolderDownload = CType(oFolderItem.GetFolder(), Shell32.Folder)
                    'Exit For
                End If
            Next
        End If
        If (oFolderDownload IsNot Nothing) Then
            Dim oFolder As Shell32.Folder = oShell.[NameSpace](sDrive)
            Dim oFile As Shell32.FolderItem2 = CType(oFolder.ParseName(sFileName), Shell32.FolderItem2)
            oFolderDownload.CopyHere(oFile, 256 Or 16)
        End If
    End If

    Declarations :

        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function LoadString(ByVal hInstance As IntPtr, ByVal uID As Integer, ByVal lpBuffer As System.Text.StringBuilder, ByVal cchBufferMax As Integer) As Integer
        End Function
    
        <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Private Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
        End Function





    • Edited by Castorix31 Sunday, May 24, 2020 9:34 AM
    Sunday, May 24, 2020 9:14 AM
  • Thanks again, I have loaded the code & have one small issue.

    I will explain the error I have in the code below

     Dim oShell As Global.Shell32.Shell = New Global.Shell32.Shell()
            Dim oFolderMyComputer As Folder = oShell.[NameSpace]

            For Each oFolderItem As Global.Shell32.FolderItem2 In oFolderMyComputer.Items()

    For whatever reason my app did not like "Shell32" and wanted to change it to "Global.Shell32" which is now changed and fine.

    However I now have an error for "In oFolderMyComputer.Items()" where the problem seems to be "In oFolderMyComputer.Items()"

    any idea what this problem might be, thanks

    Monday, May 25, 2020 4:12 AM
  • However I now have an error for "In oFolderMyComputer.Items()" 

    Which error ?

    And the line 

    Dim oFolderMyComputer As Folder = oShell.[NameSpace]

    is

    Dim oFolderMyComputer As Shell32.Folder = oShell.[NameSpace](Shell32.ShellSpecialFolderConstants.ssfDRIVES)

    Monday, May 25, 2020 4:23 AM
  • from this image I hope you can see that console is only reporting one directory on my phone, there is 2, you are reporting folder "Card", but not "Phone" does the loop need to be extended?

    Monday, May 25, 2020 5:46 AM
  • As the hierarchy is apparently different for each phone, you could use a recursive search to find the "Download" folder

    Something like this (you can reduce the depth for the recursion with a counter if there are a lot of files, to increase speed...) =>

    ' ...
    MessageBox.Show("Portable Device found : " + oFolderItemWPD.Name, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
    Dim oFolderWPD As Shell32.Folder = CType(oFolderItemWPD.GetFolder(), Shell32.Folder)
    Dim oFolderDownload As Shell32.Folder = Nothing
    RecurseFolder(oFolderWPD, "Download", oFolderDownload)
    If (oFolderDownload IsNot Nothing) Then
        Dim oFolder As Shell32.Folder = oShell.[NameSpace](sDrive)
        Dim oFile As Shell32.FolderItem2 = CType(oFolder.ParseName(sFileName), Shell32.FolderItem2)
        oFolderDownload.CopyHere(oFile, 256 Or 16)
    End If

    Private Sub RecurseFolder(oFolderParent As Shell32.Folder, sFolderToFind As String, ByRef oFolderToFind As Shell32.Folder)
        For Each oFolderItem As Shell32.FolderItem In oFolderParent.Items()
            Dim sItemName As String = oFolderItem.Name
            Dim sItemType As String = oFolderItem.Type
            ' For test
            Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
            If (sItemName = sFolderToFind) Then
                oFolderToFind = CType(oFolderItem.GetFolder(), Shell32.Folder)
                Return
            End If
            If oFolderItem.IsFolder Then
                RecurseFolder(CType(oFolderItem.GetFolder(), Shell32.Folder), sFolderToFind, oFolderToFind)
            End If
        Next
    End Sub

    Monday, May 25, 2020 7:00 AM
  • Thanks for modifying this, most appreciated, however in the following code which I have a breakpoint to ensure we get to copyhere, the file does not appear ti have been copied is there some debug code to show where it is going?

    In other words, everything executes fine and no errors, but file is not copied, am only here for next 45 mins

    If (oFolderDownload IsNot Nothing) Then
        Dim oFolder As Shell32.Folder = oShell.[NameSpace](sDrive)
        Dim oFile As Shell32.FolderItem2 = CType(oFolder.ParseName(sFileName), Shell32.FolderItem2)
        oFolderDownload.CopyHere(oFile, 256 Or 16)
    End If

    Tuesday, May 26, 2020 6:12 AM
  • Have you actualized in Explorer ?
    Tuesday, May 26, 2020 6:22 AM
  • Sorry i did not get back sooner, after running for 2nd time I get message, file already exists, so did some investigation, file is here:

    "This PC\(SamsungGalaxy Note3)\Card\Android\data\com.android.chrome\files\Download"

    Unfortuneately there are 2 download folders, the one I need is 

    "This PC\(SamsungGalaxy Note3)\Phone\Download"

    looks like I need to identify the Higher level "Phone" directory before we look for "Download"

    if you can help with that it would be appreciated, thanks

    Tuesday, May 26, 2020 6:39 AM
  • Then you can add a test on the Parent name to identify the right "Download" folder

                    Dim oFolderItemParent As Shell32.FolderItem = CType(oFolderItem.Parent, Shell32.FolderItem)
                    If (oFolderItemParent.Name = "Phone") Then
                        '...
                    End If




    • Edited by Castorix31 Tuesday, May 26, 2020 6:52 AM
    Tuesday, May 26, 2020 6:52 AM
  • can I just change:

    RecurseFolder(oFolderWPD, "Download", oFolderDownload) to 
    RecurseFolder(oFolderWPD, "Phone\Download", oFolderDownload)

    Have to leave now
    • Edited by x38class Tuesday, May 26, 2020 6:53 AM
    Tuesday, May 26, 2020 6:52 AM
  • also can i get it to overwrite existing file
    Tuesday, May 26, 2020 10:13 PM
  • Using the mod you supplied, I am getting an error for

    "CType(oFolderItem.Parent" in the line 

    Dim oFolderItemParent As Shell32.FolderItem = CType(oFolderItem.Parent, Shell32.FolderItem)

    Can you suggest a fix for this please, also I would like the existing file to be overwritten, or delete first before copy

    Thanks

    Wednesday, May 27, 2020 6:02 AM
  • Using the mod you supplied, I am getting an error for

    "CType(oFolderItem.Parent" in the line 

    Dim oFolderItemParent As Shell32.FolderItem = CType(oFolderItem.Parent, Shell32.FolderItem)

    Replace it by :

    Dim oFolderItemParent As Shell32.Folder = CType(oFolderItem.Parent, Shell32.Folder)
    If (oFolderItemParent.Title = "Phone") Then
        oFolderToFind = CType(oFolderItem.GetFolder(), Shell32.Folder)
        Return
    End If

    Wednesday, May 27, 2020 6:24 AM
  • I am a little confused, the code you supplied suggest the mod should be in the function because you put "Return", however none of the variables are refernced there.

    so I did this:

     Dim oFolderItemParent As Global.Shell32.Folder = CType(oFolderItem.Parent, Global.Shell32.Folder)
                If (oFolderItemParent.Title = "Phone") Then
                    oFolderToFind = CType(oFolderItem.GetFolder(), Global.Shell32.Folder)

                    RecurseFolder(oFolderWPD, "Download", oFolderDownload)
                    If (oFolderDownload IsNot Nothing) Then
                        Dim oFolder As Global.Shell32.Folder = oShell.[NameSpace](sDrive)
                        Dim oFile As Global.Shell32.FolderItem2 = CType(oFolder.ParseName(sFileName), Global.Shell32.FolderItem2)
                        oFolderDownload.CopyHere(oFile, 256 Or 16)
                    End If
                End If

     I now have errors where Bold is highlighted, and you are not passing oFolderToFind  to recursive function

    back in 23 hours



    • Edited by x38class Wednesday, May 27, 2020 7:24 AM
    Wednesday, May 27, 2020 7:23 AM
  • I was talking about the RecurseFolderfunction

    Just add the test on oFolderItemParent inside

    Wednesday, May 27, 2020 7:54 AM
  • The flag=16 in CopyHere should suppress the confirmation dialog box, but it doesn't...
    It only works with IFileOperation

    So, this works for me with IFileOperation and FOF_NOCONFIRMATION flag,

    but you must check sFolderPathFull to see if it contains a SID like on my phone, that I have to remove

    ("SID-{10001,,5412716544}")

    If it is different, you will have to change the Regex or it won't work...

    =>

    Dim oShell As Shell32.Shell = New Shell32.Shell()
    Dim oFolderMyComputer As Shell32.Folder = oShell.[NameSpace](Shell32.ShellSpecialFolderConstants.ssfDRIVES)
    
    Dim sSourceFile As String = "e:\test.jpg"
    Dim fi As IO.FileInfo = New IO.FileInfo(sSourceFile)
    Dim sFileName As String = fi.Name
    Dim sDrive As String = IO.Path.GetPathRoot(fi.FullName)
    
    Dim hDLL As IntPtr = LoadLibrary("C:\WINDOWS\system32\wpdshext.dll")
    Dim sbStringWPD As System.Text.StringBuilder = New System.Text.StringBuilder(260)
    LoadString(hDLL, 347, sbStringWPD, sbStringWPD.Capacity)
    
    Dim oFolderItemWPD As Shell32.FolderItem2 = Nothing
    For Each oFolderItem As Shell32.FolderItem2 In oFolderMyComputer.Items()
        Dim sItemName As String = oFolderItem.Name
        Dim sItemType As String = oFolderItem.Type
        Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
        If (sItemType = sbStringWPD.ToString()) Then
            oFolderItemWPD = oFolderItem
            Exit For
        End If
        ' Name : Archos 40 Helium - Type : Lecteur multimédia portable
    Next
    If (oFolderItemWPD IsNot Nothing) Then
        MessageBox.Show("Portable Device found : " + oFolderItemWPD.Name, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
        Dim oFolderWPD As Shell32.Folder = CType(oFolderItemWPD.GetFolder(), Shell32.Folder)
        Dim oFolderDownload As Shell32.Folder = Nothing
        'RecurseFolder(oFolderWPD, "Download", "Mémoire de stockage interne", oFolderDownload)
        RecurseFolder(oFolderWPD, "Download", "Phone", oFolderDownload)
        ' RecurseFolder(oFolderWPD, "Download", Nothing, oFolderDownload)
        If (oFolderDownload IsNot Nothing) Then
            Dim pShellItemSource As IShellItem = Nothing, pShellItemDest As IShellItem = Nothing
            Dim hr As HRESULT = SHCreateItemFromParsingName(sSourceFile, IntPtr.Zero, GetType(IShellItem).GUID, pShellItemSource)
    
            Dim sFolderPathFull As String = oFolderDownload.ParentFolder.ParseName(oFolderDownload.Title).Path
            ' ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_0e79&pid_52c2#908165c02an9577#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\SID-{10001,,5412716544}\{0000000F-0001-0001-0000-000000000000}\{00000760-0001-0001-0000-000000000000}
            ' Remove Internal Storage ID
            Dim sFolderPath As String = System.Text.RegularExpressions.Regex.Replace(sFolderPathFull, "SID.*?\\", "")
            hr = SHCreateItemFromParsingName(sFolderPath, IntPtr.Zero, GetType(IShellItem).GUID, pShellItemDest)
    
            Dim pfo As IFileOperation = CType(Activator.CreateInstance(FileOperationType), IFileOperation)
            ' Suppress confirmation Dialog Box
            hr = pfo.SetOperationFlags(FILEOP_FLAGS.FOF_NOCONFIRMATION)
            hr = pfo.CopyItem(pShellItemSource, pShellItemDest, Nothing, IntPtr.Zero)
            If (hr = HRESULT.S_OK) Then
                hr = pfo.PerformOperations()
            End If
            Marshal.ReleaseComObject(pfo)
        Else
            MessageBox.Show("Download folder not found on " + oFolderItemWPD.Name, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If
    End If
    
    Private Sub RecurseFolder(oFolderParent As Shell32.Folder, sFolderToFind As String, sParentFolderToFind As String, ByRef oFolderToFind As Shell32.Folder)
        For Each oFolderItem As Shell32.FolderItem In oFolderParent.Items()
            Dim sItemName As String = oFolderItem.Name
            Dim sItemType As String = oFolderItem.Type
            ' For test
            Console.WriteLine("Name : {0} - Type : {1}", sItemName, sItemType)
            If (sItemName = sFolderToFind) Then
                Dim oFolderItemParent As Shell32.Folder = CType(oFolderItem.Parent, Shell32.Folder)
                If (oFolderItemParent.Title = sParentFolderToFind Or sParentFolderToFind = Nothing) Then
                    oFolderToFind = CType(oFolderItem.GetFolder(), Shell32.Folder)
                    Return
                End If
            End If
            If (oFolderItem.IsFolder) Then
                RecurseFolder(CType(oFolderItem.GetFolder(), Shell32.Folder), sFolderToFind, sParentFolderToFind, oFolderToFind)
            End If
        Next
    End Sub

    Declarations :

        Public Enum HRESULT As Integer
            S_OK = 0
            S_FALSE = 1
            E_NOINTERFACE = &H80004002
            E_NOTIMPL = &H80004001
            E_FAIL = &H80004005
            E_INVALIDARG = &H80070057
            E_UNEXPECTED = &H8000FFFF
            E_OUTOFMEMORY = &H8007000E
        End Enum
    
        <ComImport()> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> <Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")>
        Public Interface IShellItem
            Function BindToHandler(ByVal pbc As IntPtr, ByRef bhid As Guid, ByRef riid As Guid, ByRef ppv As IntPtr) As HRESULT
            Function GetParent(ByRef ppsi As IShellItem) As HRESULT
            Function GetDisplayName(ByVal sigdnName As SIGDN, ByRef ppszName As System.Text.StringBuilder) As HRESULT
            Function GetAttributes(ByVal sfgaoMask As UInteger, ByRef psfgaoAttribs As UInteger) As HRESULT
            Function Compare(ByVal psi As IShellItem, ByVal hint As UInteger, ByRef piOrder As Integer) As HRESULT
        End Interface
    
        Public Enum SIGDN As Integer
            SIGDN_NORMALDISPLAY = &H0
            SIGDN_PARENTRELATIVEPARSING = &H80018001
            SIGDN_DESKTOPABSOLUTEPARSING = &H80028000
            SIGDN_PARENTRELATIVEEDITING = &H80031001
            SIGDN_DESKTOPABSOLUTEEDITING = &H8004C000
            SIGDN_FILESYSPATH = &H80058000
            SIGDN_URL = &H80068000
            SIGDN_PARENTRELATIVEFORADDRESSBAR = &H8007C001
            SIGDN_PARENTRELATIVE = &H80080001
        End Enum
    
        <ComImport()> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> <Guid("947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8")>
        Friend Interface IFileOperation
            Function Advise(ByVal pfops As IntPtr, ByRef pdwCookie As UInteger) As HRESULT
            Function Unadvise(ByVal dwCookie As UInteger) As HRESULT
            Function SetOperationFlags(ByVal dwOperationFlags As FILEOP_FLAGS) As HRESULT
            Function SetProgressMessage(<MarshalAs(UnmanagedType.LPWStr)> ByVal pszMessage As String) As HRESULT
            Function SetProgressDialog(<MarshalAs(UnmanagedType.[Interface])> ByVal popd As Object) As HRESULT
            Function SetProperties(<MarshalAs(UnmanagedType.[Interface])> ByVal pproparray As Object) As HRESULT
            Function SetOwnerWindow(ByVal hwndParent As UInteger) As HRESULT
            Function ApplyPropertiesToItem(ByVal psiItem As IShellItem) As HRESULT
            Function ApplyPropertiesToItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object) As HRESULT
            Function RenameItem(ByVal psiItem As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String, ByVal pfopsItem As IntPtr) As HRESULT
            Function RenameItems(<MarshalAs(UnmanagedType.[Interface])> ByVal pUnkItems As Object, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String) As HRESULT
            <PreserveSig()>
            Function MoveItem(ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszNewName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function MoveItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object, ByVal psiDestinationFolder As IShellItem) As HRESULT
            <PreserveSig()>
            Function CopyItem(ByVal psiItem As IShellItem, ByVal psiDestinationFolder As IShellItem, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszCopyName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function CopyItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object, ByVal psiDestinationFolder As IShellItem) As HRESULT
            Function DeleteItem(ByVal psiItem As IShellItem, ByVal pfopsItem As IntPtr) As HRESULT
            Function DeleteItems(<MarshalAs(UnmanagedType.[Interface])> ByVal punkItems As Object) As HRESULT
            Function NewItem(ByVal psiDestinationFolder As IShellItem, ByVal dwFileAttributes As System.IO.FileAttributes, <MarshalAs(UnmanagedType.LPWStr)> ByVal pszName As String,
                             <MarshalAs(UnmanagedType.LPWStr)> ByVal pszTemplateName As String, ByVal pfopsItem As IntPtr) As HRESULT
            <PreserveSig()>
            Function PerformOperations() As HRESULT
            Function GetAnyOperationsAborted() As Boolean
        End Interface
    
        <Flags>
        Public Enum FILEOP_FLAGS
            FOF_MULTIDESTFILES = &H1
            FOF_CONFIRMMOUSE = &H2
            FOF_SILENT = &H4
            FOF_RENAMEONCOLLISION = &H8
            FOF_NOCONFIRMATION = &H10
            FOF_WANTMAPPINGHANDLE = &H20
            FOF_ALLOWUNDO = &H40
            FOF_FILESONLY = &H80
            FOF_SIMPLEPROGRESS = &H100
            FOF_NOCONFIRMMKDIR = &H200
            FOF_NOERRORUI = &H400
            FOF_NOCOPYSECURITYATTRIBS = &H800
            FOF_NORECURSION = &H1000
            FOF_NO_CONNECTED_ELEMENTS = &H2000
            FOF_WANTNUKEWARNING = &H4000
            FOF_NORECURSEREPARSE = &H8000
            FOF_NO_UI = (FOF_SILENT Or FOF_NOCONFIRMATION Or FOF_NOERRORUI Or FOF_NOCONFIRMMKDIR) ' don't display any UI at all
            FOFX_NOSKIPJUNCTIONS = &H10000
            FOFX_PREFERHARDLINK = &H20000
            FOFX_SHOWELEVATIONPROMPT = &H40000
            FOFX_EARLYFAILURE = &H100000
            FOFX_PRESERVEFILEEXTENSIONS = &H200000
            FOFX_KEEPNEWERFILE = &H400000
            FOFX_NOCOPYHOOKS = &H800000
            FOFX_NOMINIMIZEBOX = &H1000000
            FOFX_MOVEACLSACROSSVOLUMES = &H2000000
            FOFX_DONTDISPLAYSOURCEPATH = &H4000000
            FOFX_DONTDISPLAYDESTPATH = &H8000000
        End Enum
    
        Public Const SFGAO_DROPTARGET = &H100L 'Objects are drop target
        Public Const SFGAO_FOLDER = &H20000000L 'Support BindToObject(IID_IShellFolder)
        Public Const SFGAO_FILESYSTEM = &H40000000L 'Is a win32 file system Object (file/folder/root)
        Public Const SFGAO_STREAM = &H400000L 'Supports BindToObject(IID_IStream)
        Public Const SFGAO_STORAGE = &H8L 'supports BindToObject(IID_IStorage)
        Public Const SFGAO_READONLY = &H40000L ' Read-only
    
        Public Const DROPEFFECT_COPY = (1)
        Public Const DROPEFFECT_MOVE = (2)
        Public Const SFGAO_CANCOPY = DROPEFFECT_COPY 'Objects can be copied    (0x1)
        Public Const SFGAO_CANMOVE = DROPEFFECT_MOVE ' Objects can be moved     (0x2)
    
        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function LoadString(ByVal hInstance As IntPtr, ByVal uID As Integer, ByVal lpBuffer As System.Text.StringBuilder, ByVal cchBufferMax As Integer) As Integer
        End Function
    
        <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Private Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
        End Function
    
        <DllImport("Shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
        Public Shared Function SHCreateItemFromParsingName(ByVal pszPath As String, ByVal pbc As IntPtr, <[In], MarshalAs(UnmanagedType.LPStruct)> ByVal riid As Guid, <Out> ByRef ppv As IShellItem) As HRESULT
        End Function
    
        Public Shared CLSID_FileOperation As Guid = New Guid("3ad05575-8857-4850-9277-11b85bdb8e09")
        Public Shared FileOperationType As Type = Type.GetTypeFromCLSID(CLSID_FileOperation)

    • Marked as answer by x38class Friday, May 29, 2020 5:42 AM
    Wednesday, May 27, 2020 11:20 AM
  • Thanks again for your interest & contribution. It may take me a while to re-configure.

    Your knowledge of identifying obscure information is much appreciated as it is way beyond my level of understanding, again many thanks

    Thursday, May 28, 2020 6:00 AM
  • To say I impressed is an understatement, the effort you have put in to solve my issue is most appreciated.

    I only get 1-2 hours a day and I have been working on this app since December, so being able to finish it is fantastic.

    Thanks again for your help

    Friday, May 29, 2020 5:45 AM