Search code examples
vb.netwindows-explorer

How to copy multiple files/folders using single windows copy GUI in VB.Net


I am making an app in VB.Net that copies many files and folders to the same directory and I wish to use windows explorer for that (so the user has GUI and I do not have to worry about showing any errors or compare files).

So, if I do this for each file/folder:

My.Computer.FileSystem.CopyDirectory(source_path, target_path, FileIO.UIOption.AllDialogs)
My.Computer.FileSystem.CopyFile(source_path, target_path, FileIO.UIOption.AllDialogs)

It works correctly and shows this window:

single copy

Which is fine, however, if I have many files and/or folders and I loop through them and call commands above, they launch a new copy window for each file/folder, instead of launching a single GUI that combines them all, like so:

multiple copy

Is it possible to combine multiple files/folders copy process into a single windows explorer copy window GUI?


Solution

  • Thanks to @Jimi, I got pointed in the direction of SHFileOperations, so i figured out how to do this. I made a small class to do this:

    Imports System.Runtime.InteropServices
    
    Public Class NativeCopy
        
        Private Enum FO_Func As Short
            FO_COPY   = &H2
            FO_DELETE = &H3
            FO_MOVE   = &H1
            FO_RENAME = &H4
        End Enum
    
        Private Structure SHFILEOPSTRUCT
    
            Public hwnd  As IntPtr
            Public wFunc As FO_Func
    
            <MarshalAs(UnmanagedType.LPWStr)>
            Public pFrom As String
    
            <MarshalAs(UnmanagedType.LPWStr)>
            Public pTo                   As String
            Public fFlags                As UShort
            Public fAnyOperationsAborted As Boolean
            Public hNameMappings         As IntPtr
    
            <MarshalAs(UnmanagedType.LPWStr)>
            Public lpszProgressTitle As String
    
        End Structure
    
        <DllImport("shell32.dll", CharSet:=CharSet.Unicode)>
        Private Shared Function SHFileOperation(
           <[In]> ByRef lpFileOp As SHFILEOPSTRUCT) As Integer
        End Function
    
        Private Shared _ShFile As SHFILEOPSTRUCT
    
        Public Shared Sub Copy(ByVal sSource As List(Of String), ByVal sTarget As String)
            _ShFile.wFunc = FO_Func.FO_COPY
            _ShFile.pFrom = String.Join(vbNullChar, sSource) + vbNullChar
            _ShFile.pTo   = sTarget
            SHFileOperation(_ShFile)
       End Sub
    
    End Class
    

    To copy files and/or folders is as simple as this:

    Dim copy_items_paths As List(Of String)
    Dim target_path      As String
    
    NativeCopy.Copy(copy_items_paths, target_path)