Jump to content

CopyFiles Default Windows ProgressBar No Ovewrite (IFileOperation)


Recommended Posts

I was needing to copy some files something like a backup of a folder without overwrite file. I found in this thread a suggestion to use _WinAPI_ShellFileOperation but for my surprise it does overwrite files all the time 🤔. So I was checking MSDN and found out that IFileOperation implemented a nice operation flag  to handle what I was needing(FOFX_KEEPNEWERFILE) so I just wrote this sample in case anyone was looking for it.

 

#include <WinAPIShellEx.au3>
;~ Global Const $FOF_ALLOWUNDO = 0x40
;~ Global Const $FOF_CONFIRMMOUSE = 0x2
;~ Global Const $FOF_FILESONLY = 0x80
;~ Global Const $FOF_MULTIDESTFILES = 0x1
;~ Global Const $FOF_NO_CONNECTED_ELEMENTS = 0x2000
;~ Global Const $FOF_NOCONFIRMATION = 0x10
;~ Global Const $FOF_NOCONFIRMMKDIR = 0x200
;~ Global Const $FOF_NOCOPYSECURITYATTRIBS = 0x800
;~ Global Const $FOF_NOERRORUI = 0x400
;~ Global Const $FOF_NORECURSION = 0x1000
;~ Global Const $FOF_RENAMEONCOLLISION = 0x8
;~ Global Const $FOF_SILENT = 0x4
;~ Global Const $FOF_SIMPLEPROGRESS = 0x100
;~ Global Const $FOF_WANTMAPPINGHANDLE = 0x20
;~ Global Const $FOF_WANTNUKEWARNING = 0x4000
Global Const $FOFX_ADDUNDORECORD = 0x20000000
Global Const $FOFX_NOSKIPJUNCTIONS = 0x00010000
Global Const $FOFX_PREFERHARDLINK = 0x00020000
Global Const $FOFX_SHOWELEVATIONPROMPT = 0x00040000
Global Const $FOFX_EARLYFAILURE = 0x00100000
Global Const $FOFX_PRESERVEFILEEXTENSIONS = 0x00200000
Global Const $FOFX_KEEPNEWERFILE = 0x00400000
Global Const $FOFX_NOCOPYHOOKS = 0x00800000
Global Const $FOFX_NOMINIMIZEBOX = 0x01000000
Global Const $FOFX_MOVEACLSACROSSVOLUMES = 0x02000000
Global Const $FOFX_DONTDISPLAYSOURCEPATH = 0x04000000
Global Const $OFX_DONTDISPLAYDESTPATH = 0x08000000
Global Const $FOFX_RECYCLEONDELETE = 0x00080000
Global Const $FOFX_REQUIREELEVATION = 0x10000000
Global Const $FOFX_COPYASDOWNLOAD = 0x40000000
Global Const $FOFX_DONTDISPLAYLOCATIONS = 0x80000000


Global Const $IID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}"
Global Const $dtag_IShellItem = _
        "BindToHandler hresult(ptr;clsid;clsid;ptr*);" & _
        "GetParent hresult(ptr*);" & _
        "GetDisplayName hresult(int;ptr*);" & _
        "GetAttributes hresult(int;int*);" & _
        "Compare hresult(ptr;int;int*);"

Global Const $IID_IShellItemArray = "{b63ea76d-1f85-456f-a19c-48159efa858b}"
Global Const $dtagIShellItemArray = "BindToHandler hresult();GetPropertyStore hresult();" & _
        "GetPropertyDescriptionList hresult();GetAttributes hresult();GetCount hresult(dword*);" & _
        "GetItemAt hresult();EnumItems hresult();"

Global Const $BHID_EnumItems = "{94F60519-2850-4924-AA5A-D15E84868039}"
Global Const $IID_IEnumShellItems = "{70629033-e363-4a28-a567-0db78006e6d7}"
Global Const $dtagIEnumShellItems = "Next hresult(ulong;ptr*;ulong*);Skip hresult();Reset hresult();Clone hresult();"


Global Const $CLSID_IFileOperation = "{3AD05575-8857-4850-9277-11B85BDB8E09}"
Global Const $IID_IFileOperation = "{947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8}"
Global Const $dtagIFileOperation = "Advise hresult(ptr;dword*);" & _
        "Unadvise hresult(dword);" & _
        "SetOperationFlags hresult(dword);" & _
        "SetProgressMessage hresult(wstr);" & _
        "SetProgressDialog hresult(ptr);" & _
        "SetProperties hresult(ptr);" & _
        "SetOwnerWindow hresult(hwnd);" & _
        "ApplyPropertiesToItem hresult(ptr);" & _
        "ApplyPropertiesToItems hresult(ptr);" & _
        "RenameItem hresult(ptr;wstr;ptr);" & _
        "RenameItems hresult(ptr;wstr);" & _
        "MoveItem hresult(ptr;ptr;wstr;ptr);" & _
        "MoveItems hresult(ptr;ptr);" & _
        "CopyItem hresult(ptr;ptr;wstr;ptr);" & _
        "CopyItems hresult(ptr;ptr);" & _
        "DeleteItem hresult(ptr;ptr);" & _
        "DeleteItems hresult(ptr);" & _
        "NewItem hresult(ptr;dword;wstr;wstr;ptr);" & _
        "PerformOperations hresult();" & _
        "GetAnyOperationsAborted hresult(ptr*);"


_Test()

Func _Test()
    Local $sPathFrom = @ScriptDir & "\PathFrom\"
    Local $sPathTo = @ScriptDir & "\PathTo\"

    DirRemove($sPathFrom, 1)
    DirRemove($sPathTo, 1)

    DirCreate($sPathFrom)
    For $i = 1 To 5000
        FileWrite($sPathFrom & $i & ".txt", "Hello World - " & $i)
    Next

    _WinAPI_ShellFileOperation($sPathFrom & "*.*", $sPathTo, $FO_COPY, BitOR($FOF_NOERRORUI, $FOF_NOCONFIRMATION))
    ;update file From and To
    FileWrite($sPathFrom & 1 & ".txt", " Only this should be update in 'To' Folder")
    FileWrite($sPathTo & 2 & ".txt", " This should not be overwritten but it does :(")
    MsgBox(0, "ShellFileOperation", "Check these files: " & @CRLF & $sPathFrom & 1 & ".txt" & @CRLF & @CRLF & $sPathTo & 2 & ".txt")
    _WinAPI_ShellFileOperation($sPathFrom & "*.*", $sPathTo, $FO_COPY, BitOR($FOF_NOERRORUI, $FOF_NOCONFIRMATION))
    MsgBox(0, "ShellFileOperation", "Check these files: " & @CRLF & $sPathFrom & 1 & ".txt" & @CRLF & @CRLF & $sPathTo & 2 & ".txt")



    ;update file From and To
    FileWrite($sPathFrom & 1 & ".txt", " - I was updated again :-S")
    FileWrite($sPathTo & 2 & ".txt", " This will not be overwritten :)")
    MsgBox(0, "IFileOperation", "Check these files: " & @CRLF & $sPathFrom & 1 & ".txt" & @CRLF & @CRLF & $sPathTo & 2 & ".txt")
    _IFileOperationCopyFiles($sPathFrom, $sPathTo)
    MsgBox(0, "IFileOperation", "Check these files: " & @CRLF & $sPathFrom & 1 & ".txt" & @CRLF & @CRLF & $sPathTo & 2 & ".txt")


    DirRemove($sPathFrom, 1)
    DirRemove($sPathTo, 1)
EndFunc   ;==>_Test



Func _IFileOperationCopyFiles($sPathFrom, $sPathTo, $iFlags = BitOR($FOF_NOERRORUI, $FOFX_KEEPNEWERFILE, $FOFX_NOCOPYHOOKS, $FOF_NOCONFIRMATION))
    If Not FileExists($sPathFrom) Then
        Return SetError(1, 0, False)
    EndIf

    If Not FileExists($sPathTo) Then
        DirCreate($sPathTo)
    EndIf


    Local $tIIDIShellItem = CLSIDFromString($IID_IShellItem)
    Local $tIIDIShellItemArray = CLSIDFromString($IID_IShellItemArray)


    Local $oIFileOperation = ObjCreateInterface($CLSID_IFileOperation, $IID_IFileOperation, $dtagIFileOperation)
    If Not IsObj($oIFileOperation) Then Return SetError(2, 0, False)


    Local $pIShellItemFrom = 0
    Local $pIShellItemTo = 0


    _SHCreateItemFromParsingName($sPathFrom, 0, DllStructGetPtr($tIIDIShellItem), $pIShellItemFrom)
    _SHCreateItemFromParsingName($sPathTo, 0, DllStructGetPtr($tIIDIShellItem), $pIShellItemTo)


    If Not $pIShellItemFrom Or Not $pIShellItemTo Then Return SetError(3, 0, False)

    Local $oIShellItem = ObjCreateInterface($pIShellItemFrom, $IID_IShellItem, $dtag_IShellItem)
    Local $pEnum = 0
    $oIShellItem.BindToHandler(0, $BHID_EnumItems, $IID_IEnumShellItems, $pEnum)
    Local $oIEnumShellItems = ObjCreateInterface($pEnum, $IID_IEnumShellItems, $dtagIEnumShellItems)

    If Not $pEnum Then Return SetError(4, 0, False)

    $oIFileOperation.SetOperationFlags($iFlags)
    Local $pItem = 0
    Local $iFeched = 0
    While $oIEnumShellItems.Next(1, $pItem, $iFeched) = 0
        $oIFileOperation.CopyItems($pItem, $pIShellItemTo)
    WEnd

    Return $oIFileOperation.PerformOperations() = 0

EndFunc   ;==>_IFileOperationCopyFiles


Func _SHCreateItemFromParsingName($szPath, $pbc, $riid, ByRef $pv)
    Local $aRes = DllCall("shell32.dll", "long", "SHCreateItemFromParsingName", "wstr", $szPath, "ptr", $pbc, "ptr", $riid, "ptr*", 0)
    If @error Then Return SetError(1, 0, @error)
    $pv = $aRes[4]
    Return $aRes[0]
EndFunc   ;==>_SHCreateItemFromParsingName


Func CLSIDFromString($sString)
    Local $tCLSID = DllStructCreate("dword;word;word;byte[8]")
    Local $aRet = DllCall("Ole32.dll", "long", "CLSIDFromString", "wstr", $sString, "ptr", DllStructGetPtr($tCLSID))
    If @error Then Return SetError(1, 0, @error)
    If $aRet[0] <> 0 Then Return SetError(2, $aRet[0], 0)
    Return $tCLSID
EndFunc   ;==>CLSIDFromString

 

 

Saludos

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...