Jump to content

_ExplorerCopy options


Recommended Posts

I'm using _ExplorerCopy() with this code:

Local $SHFILEOPSTRUCT, $aFiles, $SourceStruct, $DestStruct, $iSourceList, $iLen

$SHFILEOPSTRUCT = DllStructCreate("hwnd hWnd;uint wFunc;ptr pFrom;ptr pTo;int fFlags;" & _
"int fAnyOperationsAborted;ptr hNameMappings;ptr lpszProgressTitle")

DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NO_UI)

$aFiles = StringSplit($Source, "|")
For $i = 1 To $aFiles[0]
    $iSourceList &= $aFiles[$i] & Chr(0)
Next

$iSourceList &= Chr(0) & Chr(0)
$iSourceList = StringToBinary($iSourceList)
$iLen = BinaryLen($iSourceList)
$SourceStruct = DllStructCreate("byte[" & $iLen & "]")

DllStructSetData($SourceStruct, 1, $iSourceList)

$DestStruct = DllStructCreate("char[" & StringLen($Dest) + 2 & "]")
DllStructSetData($DestStruct, 1, $Dest)
DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 1)
DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 2)

DllStructSetData($SHFILEOPSTRUCT, "hWnd", 0)
DllStructSetData($SHFILEOPSTRUCT, "wFunc", $FO_COPY)
DllStructSetData($SHFILEOPSTRUCT, "pFrom", DllStructGetPtr($SourceStruct))
DllStructSetData($SHFILEOPSTRUCT, "pTo", DllStructGetPtr($DestStruct))
DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NOCONFIRMATION)

DllCall("shell32.dll", "int", "SHFileOperation", "ptr", DllStructGetPtr($SHFILEOPSTRUCT))

;Verify that file was copied.
If FileExists($Dest) Then
    If $pStartup_log <> "" Then
        _FileWriteLog($pStartup_log, $CalledBy & ": Copied " & $Source & " to " & $Dest, -1);writes to end of file
    EndIf
Else
    MsgBox(0, $ThisFunc, $Dest & " does not exist.")
EndIf

Return

But when it finds a file or folder that doesn't exist on the backup drive, it still insists on asking for confirmation. Because I loop through a large array of files, I can't leave it run unattended in case it asks me to click OK. I was hoping that the $FOF_NO_UI param would prevent this.

Is there a way to have it just copy without asking each time?



 

Link to comment
Share on other sites

I think FOF_NO_UI is the proper flag. Perhaps the problem is, that you are overwriting this flag with only FOF_NOCONFIRMATION in the line just before the DllCall.

Link to comment
Share on other sites

I think FOF_NO_UI is the proper flag. Perhaps the problem is, that you are overwriting this flag with only FOF_NOCONFIRMATION in the line just before the DllCall.

 

I will try this. I don't know anything about DllCalls, so I was just guessing. But I think you're right.

I'll also try changing it to $FOF_NOCONFIRMMKDIR as recommended by Terenz to see the difference. I'll let you know how it worked.

Thank you LarsJ and Terenz.

Link to comment
Share on other sites

I think FOF_NO_UI is the proper flag. Perhaps the problem is, that you are overwriting this flag with only FOF_NOCONFIRMATION in the line just before the DllCall.

OK, tried $FOF_NOCONFIRMMKDIR alone, then FOF_NO_UI. FOF_NO_UI is what I really needed. But the problem was exactly what you had pointed out. So I changed the param to match FOF_NO_UI. That's because I have no clue how to work with DLLs. Thanks for pointing that out, LarsJ.

Here's the final code:

#Region: _ExplorerCopy($Source, $Dest, $CalledBy, $pStartup_log)
    Func _ExplorerCopy($Source, $Dest, $CalledBy, $pStartup_log)
        Local $ThisFunc = "_ExplorerCopy"

        Local $SHFILEOPSTRUCT, $aFiles, $SourceStruct, $DestStruct, $iSourceList, $iLen
            
        $SHFILEOPSTRUCT = DllStructCreate("hwnd hWnd;uint wFunc;ptr pFrom;ptr pTo;int fFlags;" & _
        "int fAnyOperationsAborted;ptr hNameMappings;ptr lpszProgressTitle")
            
        DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NO_UI)
            
        $aFiles = StringSplit($Source, "|")
        For $i = 1 To $aFiles[0]
            $iSourceList &= $aFiles[$i] & Chr(0)
        Next
            
        $iSourceList &= Chr(0) & Chr(0)
        $iSourceList = StringToBinary($iSourceList)
        $iLen = BinaryLen($iSourceList)
        $SourceStruct = DllStructCreate("byte[" & $iLen & "]")
            
        DllStructSetData($SourceStruct, 1, $iSourceList)

        $DestStruct = DllStructCreate("char[" & StringLen($Dest) + 2 & "]")
        DllStructSetData($DestStruct, 1, $Dest)
        DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 1)
        DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 2)

        DllStructSetData($SHFILEOPSTRUCT, "hWnd", 0)
        DllStructSetData($SHFILEOPSTRUCT, "wFunc", $FO_COPY)
        DllStructSetData($SHFILEOPSTRUCT, "pFrom", DllStructGetPtr($SourceStruct))
        DllStructSetData($SHFILEOPSTRUCT, "pTo", DllStructGetPtr($DestStruct))
        DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NO_UI)
            
        DllCall("shell32.dll", "int", "SHFileOperation", "ptr", DllStructGetPtr($SHFILEOPSTRUCT))
            
        ;Verify that file was copied.
        If FileExists($Dest) Then
            If $pStartup_log <> "" Then
                _FileWriteLog($pStartup_log, $CalledBy & ": Copied " & $Source & " to " & $Dest, -1);writes to end of file
            EndIf
        Else
            MsgBox(0, $ThisFunc, $Dest & " does not exist.")
        EndIf
        
        Return

    EndFunc   ;==>_ExplorerCopy
#Endregion
Link to comment
Share on other sites

I think FOF_NO_UI is the proper flag. Perhaps the problem is, that you are overwriting this flag with only FOF_NOCONFIRMATION in the line just before the DllCall.

OK, tried $FOF_NOCONFIRMMKDIR alone, then FOF_NO_UI. FOF_NO_UI is what I really needed. But the problem was exactly what you had pointed out. So I changed the param to match FOF_NO_UI. That's because I have no clue how to work with DLLs. Thanks for pointing that out, LarsJ.

Here's the final code:

#Region: _ExplorerCopy($Source, $Dest, $CalledBy, $pStartup_log)
    Func _ExplorerCopy($Source, $Dest, $CalledBy, $pStartup_log)
        Local $ThisFunc = "_ExplorerCopy"

        Local $SHFILEOPSTRUCT, $aFiles, $SourceStruct, $DestStruct, $iSourceList, $iLen
            
        $SHFILEOPSTRUCT = DllStructCreate("hwnd hWnd;uint wFunc;ptr pFrom;ptr pTo;int fFlags;" & _
        "int fAnyOperationsAborted;ptr hNameMappings;ptr lpszProgressTitle")
            
        DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NO_UI)
            
        $aFiles = StringSplit($Source, "|")
        For $i = 1 To $aFiles[0]
            $iSourceList &= $aFiles[$i] & Chr(0)
        Next
            
        $iSourceList &= Chr(0) & Chr(0)
        $iSourceList = StringToBinary($iSourceList)
        $iLen = BinaryLen($iSourceList)
        $SourceStruct = DllStructCreate("byte[" & $iLen & "]")
            
        DllStructSetData($SourceStruct, 1, $iSourceList)

        $DestStruct = DllStructCreate("char[" & StringLen($Dest) + 2 & "]")
        DllStructSetData($DestStruct, 1, $Dest)
        DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 1)
        DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 2)

        DllStructSetData($SHFILEOPSTRUCT, "hWnd", 0)
        DllStructSetData($SHFILEOPSTRUCT, "wFunc", $FO_COPY)
        DllStructSetData($SHFILEOPSTRUCT, "pFrom", DllStructGetPtr($SourceStruct))
        DllStructSetData($SHFILEOPSTRUCT, "pTo", DllStructGetPtr($DestStruct))
        DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NO_UI)
            
        DllCall("shell32.dll", "int", "SHFileOperation", "ptr", DllStructGetPtr($SHFILEOPSTRUCT))
            
        ;Verify that file was copied.
        If FileExists($Dest) Then
            If $pStartup_log <> "" Then
                _FileWriteLog($pStartup_log, $CalledBy & ": Copied " & $Source & " to " & $Dest, -1);writes to end of file
            EndIf
        Else
            MsgBox(0, $ThisFunc, $Dest & " does not exist.")
        EndIf
        
        Return

    EndFunc   ;==>_ExplorerCopy
#Endregion
Link to comment
Share on other sites

 

OK, tried $FOF_NOCONFIRMMKDIR alone, then FOF_NO_UI. FOF_NO_UI is what I really needed. But the problem was exactly what you had pointed out. So I changed the param to match FOF_NO_UI. That's because I have no clue how to work with DLLs. Thanks for pointing that out, LarsJ.

Here's the final code:

#Region: _ExplorerCopy($Source, $Dest, $CalledBy, $pStartup_log)
    Func _ExplorerCopy($Source, $Dest, $CalledBy, $pStartup_log)
        Local $ThisFunc = "_ExplorerCopy"

        Local $SHFILEOPSTRUCT, $aFiles, $SourceStruct, $DestStruct, $iSourceList, $iLen
            
        $SHFILEOPSTRUCT = DllStructCreate("hwnd hWnd;uint wFunc;ptr pFrom;ptr pTo;int fFlags;" & _
        "int fAnyOperationsAborted;ptr hNameMappings;ptr lpszProgressTitle")
            
        DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NO_UI)
            
        $aFiles = StringSplit($Source, "|")
        For $i = 1 To $aFiles[0]
            $iSourceList &= $aFiles[$i] & Chr(0)
        Next
            
        $iSourceList &= Chr(0) & Chr(0)
        $iSourceList = StringToBinary($iSourceList)
        $iLen = BinaryLen($iSourceList)
        $SourceStruct = DllStructCreate("byte[" & $iLen & "]")
            
        DllStructSetData($SourceStruct, 1, $iSourceList)

        $DestStruct = DllStructCreate("char[" & StringLen($Dest) + 2 & "]")
        DllStructSetData($DestStruct, 1, $Dest)
        DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 1)
        DllStructSetData($DestStruct, 1, 0, StringLen($Dest) + 2)

        DllStructSetData($SHFILEOPSTRUCT, "hWnd", 0)
        DllStructSetData($SHFILEOPSTRUCT, "wFunc", $FO_COPY)
        DllStructSetData($SHFILEOPSTRUCT, "pFrom", DllStructGetPtr($SourceStruct))
        DllStructSetData($SHFILEOPSTRUCT, "pTo", DllStructGetPtr($DestStruct))
        DllStructSetData($SHFILEOPSTRUCT, "fFlags", $FOF_NO_UI)
            
        DllCall("shell32.dll", "int", "SHFileOperation", "ptr", DllStructGetPtr($SHFILEOPSTRUCT))
            
        ;Verify that file was copied.
        If FileExists($Dest) Then
            If $pStartup_log <> "" Then
                _FileWriteLog($pStartup_log, $CalledBy & ": Copied " & $Source & " to " & $Dest, -1);writes to end of file
            EndIf
        Else
            MsgBox(0, $ThisFunc, $Dest & " does not exist.")
        EndIf
        
        Return

    EndFunc   ;==>_ExplorerCopy
#Endregion

Well dang! It seemed like it worked from one script. But when I tried to call _ExplorerCopy() from a different script, it now asks to create every missing file. It's calling the same _ExplorerCopy() in my UDF folder with the same params, etc.

So I'm at a loss as to what causes ExplorerCopy to do that.

Any idea?

Link to comment
Share on other sites

I would recommend you to use _WinAPI_ShellFileOperation (AutoIt 3.3.10 or later) like this:

 

#include <WinAPIShellEx.au3>

Example()

Func Example()
  _WinAPI_ShellFileOperation( "C:\WINDOWS\Temp\AutoIt\Source\tst01.au3", "C:\WINDOWS\Temp\AutoIt\Dest", $FO_COPY, $FOF_NO_UI )

  ;Local $aFiles[3] = [ "C:\WINDOWS\Temp\AutoIt\Source\tst01.au3", _
  ;                     "C:\WINDOWS\Temp\AutoIt\Source\tst02.au3", _
  ;                     "C:\WINDOWS\Temp\AutoIt\Source\tst03.au3" ]
  ;_WinAPI_ShellFileOperation( $aFiles, "C:\WINDOWS\Temp\AutoIt\Dest", $FO_COPY, $FOF_NO_UI )
EndFunc

I'm not getting any conformation dialogs. Neither when I copy a new file or overwrite an existing file in the destination folder. Do you have the necessary rights in the destination folder?

Link to comment
Share on other sites

I would recommend you to use _WinAPI_ShellFileOperation (AutoIt 3.3.10 or later) like this:

 

#include <WinAPIShellEx.au3>

Example()

Func Example()
  _WinAPI_ShellFileOperation( "C:\WINDOWS\Temp\AutoIt\Source\tst01.au3", "C:\WINDOWS\Temp\AutoIt\Dest", $FO_COPY, $FOF_NO_UI )

  ;Local $aFiles[3] = [ "C:\WINDOWS\Temp\AutoIt\Source\tst01.au3", _
  ;                     "C:\WINDOWS\Temp\AutoIt\Source\tst02.au3", _
  ;                     "C:\WINDOWS\Temp\AutoIt\Source\tst03.au3" ]
  ;_WinAPI_ShellFileOperation( $aFiles, "C:\WINDOWS\Temp\AutoIt\Dest", $FO_COPY, $FOF_NO_UI )
EndFunc
I'm not getting any conformation dialogs. Neither when I copy a new file or overwrite an existing file in the destination folder. Do you have the necessary rights in the destination folder?

 

Fantastic! That works great! I was able to replace calls to _ExplorerCopy() with _WinAPI_ShellFileOperation and passing the same params, and I didn't get any confirms!

Thanks much, LarsJ! Now I can go do something while I'm backing things up.

Can you recommend a good tutorial on DLLs, pointers, indexes to pointers, DllStruct, and all that stuff for a newbie? I'm not a classically trained programmer like most of you guys. I am a self-taught "scripter." So I didn't get the classes on that stuff. When I look at what you guys can do with DLLs, I don't understand what's being done. So I'd really like to get some good insight into this. I've searched for tutorials, but none were basic enough.

Link to comment
Share on other sites

You can find a small 10 page tutorial here. Then you can continue googling from there.

Edited by LarsJ
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...