Jump to content

Recommended Posts

Posted

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?



 

Posted

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.

Posted

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.

Posted

LarsJ is right

From APIShellExConstants.au3 :

Global Const $FOF_NO_UI = BitOR($FOF_NOCONFIRMATION, $FOF_NOCONFIRMMKDIR, $FOF_NOERRORUI, $FOF_SILENT)

Posted

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
Posted

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
Posted

 

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?

Posted

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?

Posted

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.

Posted (edited)

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

Edited by LarsJ
Posted

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

Cool! Thanks much, LarsJ. You've been a great help!

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
×
×
  • Create New...