Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Text
Friend Class Win32API
<Flags()> _
Public Enum FILEOP_FLAGS As UShort
FOF_MULTIDESTFILES = &H1
FOF_CONFIRMMOUSE = &H2
''' <summary>
''' Don't create progress/report
''' </summary>
FOF_SILENT = &H4
FOF_RENAMEONCOLLISION = &H8
''' <summary>
''' Don't prompt the user.
''' </summary>
FOF_NOCONFIRMATION = &H10
''' <summary>
''' Fill in SHFILEOPSTRUCT.hNameMappings.
''' Must be freed using SHFreeNameMappings
''' </summary>
FOF_WANTMAPPINGHANDLE = &H20
FOF_ALLOWUNDO = &H40
''' <summary>
''' On *.*, do only files
''' </summary>
FOF_FILESONLY = &H80
''' <summary>
''' Don't show names of files
''' </summary>
FOF_SIMPLEPROGRESS = &H100
''' <summary>
''' Don't confirm making any needed dirs
''' </summary>
FOF_NOCONFIRMMKDIR = &H200
''' <summary>
''' Don't put up error UI
''' </summary>
FOF_NOERRORUI = &H400
''' <summary>
''' Dont copy NT file Security Attributes
''' </summary>
FOF_NOCOPYSECURITYATTRIBS = &H800
''' <summary>
''' Don't recurse into directories.
''' </summary>
FOF_NORECURSION = &H1000
''' <summary>
''' Don't operate on connected elements.
''' </summary>
FOF_NO_CONNECTED_ELEMENTS = &H2000
''' <summary>
''' During delete operation,
''' warn if nuking instead of recycling (partially overrides FOF_NOCONFIRMATION)
''' </summary>
FOF_WANTNUKEWARNING = &H4000
''' <summary>
''' Treat reparse points as objects, not containers
''' </summary>
FOF_NORECURSEREPARSE = &H8000
End Enum
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure SHFILEOPSTRUCT
Public hwnd As IntPtr
<MarshalAs(UnmanagedType.U4)> Public wFunc As FileFuncFlags
<MarshalAs(UnmanagedType.LPWStr)> Public pFrom As String
<MarshalAs(UnmanagedType.LPWStr)> Public pTo As String
<MarshalAs(UnmanagedType.U2)> Public fFlags As FILEOP_FLAGS
<MarshalAs(UnmanagedType.Bool)> Public fAnyOperationsAborted As Boolean
Public hNameMappings As IntPtr
<MarshalAs(UnmanagedType.LPWStr)> Public lpszProgressTitle As String ' only used if FOF_SIMPLEPROGRESS
End Structure
<Flags()> _
Public Enum FileFuncFlags As UInteger
FO_MOVE = &H1
FO_COPY = &H2
FO_DELETE = &H3
FO_RENAME = &H4
End Enum
<DllImport("shell32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Public Shared Function SHFileOperation(<MarshalAs(UnmanagedType.Struct)> ByRef lpFileOp As SHFILEOPSTRUCT) As Integer
End Function
End Class
Public Class ShellFileOperations
Public Shared Function MoveFiles(ByVal files As IList(Of String), ByVal destinationPath As String) As Boolean
If CheckAllFilesExist(files) Then
Return CopyOrMoveFilesAndFolders(files, destinationPath, True)
Else
Throw New FileNotFoundException("One of the source files doesn't exist")
End If
End Function
Public Shared Function MoveFolders(ByVal folders As IList(Of String), ByVal destinationPath As String) As Boolean
If CheckAllFoldersExist(folders) Then
Return CopyOrMoveFilesAndFolders(folders, destinationPath, True)
Else
Throw New FileNotFoundException("One of the source files doesn't exist")
End If
End Function
Public Shared Function CopyFiles(ByVal files As IList(Of String), ByVal destinationPath As String) As Boolean
If CheckAllFilesExist(files) Then
Return CopyOrMoveFilesAndFolders(files, destinationPath, False)
Else
Throw New FileNotFoundException("One of the source files doesn't exist")
End If
End Function
Public Shared Function CopyFolders(ByVal folders As IList(Of String), ByVal destinationPath As String) As Boolean
If CheckAllFoldersExist(folders) Then
Return CopyOrMoveFilesAndFolders(folders, destinationPath, False)
Else
Throw New FileNotFoundException("One of the source files doesn't exist")
End If
End Function
Private Shared Function CopyOrMoveFilesAndFolders(ByVal filesOrFolders As IList(Of String), ByVal destinationPath As String, ByVal move As Boolean) As Boolean
Dim shOP As Win32API.SHFILEOPSTRUCT
shOP.fFlags = Win32API.FILEOP_FLAGS.FOF_MULTIDESTFILES
shOP.hNameMappings = IntPtr.Zero
shOP.hwnd = IntPtr.Zero
shOP.lpszProgressTitle = ""
If move Then
shOP.wFunc = Win32API.FileFuncFlags.FO_MOVE
Else
shOP.wFunc = Win32API.FileFuncFlags.FO_COPY
End If
shOP.pFrom = MakeShellList(filesOrFolders)
shOP.pTo = MakeShellList(MakeDestFileList(filesOrFolders, destinationPath))
'Function returns zero on success
Return Not CBool(Win32API.SHFileOperation(shOP))
End Function
Private Shared Function MakeDestFileName(ByVal sourceFullPath As String, ByVal destPath As String)
Dim fileNameOnly As String = Path.GetFileName(sourceFullPath)
Return destPath + "\" + fileNameOnly
End Function
Private Shared Function MakeDestFileList(ByVal files As IList(Of String), ByVal destPath As String) As String()
Dim ret As New List(Of String)
For Each f As String In files
ret.Add(MakeDestFileName(f, destPath))
Next
Return ret.ToArray
End Function
Private Shared Function MakeShellList(ByVal strings As IList(Of String)) As String
Dim sb As New StringBuilder
For Each Strn As String In strings
sb.Append(Strn)
sb.Append(ChrW(0))
Next
sb.Append(ChrW(0))
Return sb.ToString
End Function
Private Shared Function CheckAllFilesExist(ByVal files As IList(Of String)) As Boolean
For Each File As String In files
If IO.File.Exists(File) = False Then
Return False
End If
Next
Return True
End Function
Private Shared Function CheckAllFoldersExist(ByVal folders As IList(Of String)) As Boolean
For Each folder As String In folders
If IO.Directory.Exists(folder) = False Then
Return False
End If
Next
Return True
End Function
End Class