Sign in to follow this  
Followers 0
omikron48

Interrupting FileCopy

7 posts in this topic

Recently, I made an upload script so I can push files onto our servers using queued uploads. I did it so I could just leave my workstation uploading files all night and tell which uploads failed when I checked it in the morning.

Thing is, I tried making an interrupt hotkey to stop the upload script so I could terminate it early. From my observation, the hotkey doesn't interrupt my script when it's in the middle of executing FileCopy. The script interrupt only triggers after the FileCopy finishes.

So my question are: Is FileCopy a "blocking" function as defined in HotKeySet? Is there a way to cut my upload early without resorting to a file by file copy script? Is a file by file copy better than just copying a whole directory at once?

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Yep, the standard FileCopy() is a blocking function.

Looking into the MSDN documentation of CopyFileEx (for which there are UDFs around), I see that you can issue a PROGRESS_CANCEL using the CopyProgressRoutine.

Edit: Searching the forum brought up these two posts providing methods to cancel running file copy functions:

By Yashied (method 1): #717740

By rasim (long time not seen!): #568177

Edited by KaFu

Share this post


Link to post
Share on other sites

Forgot to add DirCopy too, since I also upload whole folders other than single files.

Does CopyFileEx work on directories too? Or do I resort to doing a file by file copy using CopyFileEx?

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

I can't seem to make _WinAPI_CopyFileEx work for me. Even a simple filecopy to a parent folder fails.

Here's my trial code:

#include <Constants.au3>
#include <File.au3>
#include <Misc.au3>
#include <WinAPIEx.au3>
Opt("MustDeclareVars", 1)

Global $ininame = "_" & StringReplace(@ScriptName, ".exe", "") & ".ini"
Global $section = "Options"
;check if .ini file exists
If Not FileExists($ininame) Then
    MsgBox(0x2030, "Error", "No """ & $ininame & """! Writing empty .ini file.")
    _CreateINI()
    Exit
EndIf

Global $hotkey = IniRead($ininame, $section, "InterruptKey", "{PAUSE}")
Global $tooltipx = IniRead($ininame, $section, "ToolTipX", @DesktopWidth)
Global $tooltipy = IniRead($ininame, $section, "ToolTipY", @DesktopHeight)
Global $targetpath = IniRead($ininame, $section, "TargetPath", "Error")
Global $listpath = IniRead($ininame, $section, "ListPath", "Error")
Global $logpath = IniRead($ininame, $section, "LogPath", "Error")
Global $interrupt = 0
Global $pass = 0
Global $fail = 0
Global $fhandle = 0
Global $targets
Global $title = ""
Global $text = ""

;check input in .ini file
If StringCompare($targetpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid TargetPath!")
    Exit
ElseIf StringCompare($listpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid ListPath!")
    Exit
ElseIf StringCompare($logpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid LogPath!")
    Exit
EndIf

;check that file/folder to be copied and list of copy locations exist
If FileExists($targetpath) == 0 Then
    MsgBox(0x2000, "Error", "TargetPath does not exist!")
    Exit
ElseIf FileExists($listpath) == 0 Then
    MsgBox(0x2000, "Error", "ListPath does not exist!")
    Exit
EndIf

HotKeySet($hotkey, "_SetInterrupt")
Global $hProgressRoutine

;read list fo copy locations into array
If _FileReadToArray($listpath, $targets) Then
    Local $avgtime = 0
    Local $time = 0
    Local $start = TimerInit()
    Local $i
    _WriteLog("Starting Log: " & _GetDate() & " " & _GetTime())
    ;iterate for each copy location
    For $i = 1 To $targets[0]
        If $interrupt Then
            ExitLoop
        EndIf
        ;recalculate average after first upload
        If $i <> 1 Then
            $avgtime = $time / ($i - 1)
        EndIf
        ;for display purposes (currently unused)
        $title = StringReplace(@ScriptName, ".exe", "") & " (" & $i & "/" & $targets[0] & ")" & " [P: " & $pass & " F: " & $fail & "]"
        $text = "Copy To: " & $targets[$i] & @CRLF & "Started: " & _GetTime() & " Avg Time: " & _ConvertTime($avgtime)
        If FileExists($targets[$i]) == 0 Then
            DirCreate($targets[$i])
        EndIf
        $hProgressRoutine = DllCallbackRegister('_Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;ptr')
        If _WinAPI_CopyFileEx(FileGetShortName($targetpath), FileGetShortName($targets[$i]),  DllCallBackGetPtr($hProgressRoutine)) Then
            _WriteLog("[" & _GetTime() & "] SUCCESS FILE COPY: " & $targets[$i])
            $pass += 1
        Else
            _WriteLog("[" & _GetTime() & "] " & @TAB & "FAILED FILE COPY: " & $targets[$i])
            $fail += 1
        EndIf
        DllCallbackFree($hProgressRoutine)
        $time = TimerDiff($start)
    Next
Else
    MsgBox(0x2000, "Error", "Unable to generate targets list!")
EndIf

;called on script close
Func OnAutoItExit()
    _WriteLog("Ending Log: " & _GetDate() & " " & _GetTime() & " [P: " & $pass & " F: " & $fail & "]")
EndFunc

Func _Progress($iTotalFileSize, $iTotalBytesTransferred, $iStreamSize, $iStreamBytesTransferred, $iStreamNumber, $iCallbackReason, $hSourceFile, $hDestinationFile, $iData)
    If $interrupt == 1 Then
        _WriteLog("[" & _GetTime() & "] UPLOAD INTERRUPTED!!!")
        Return $PROGRESS_CANCEL
    Else
        Return $PROGRESS_CONTINUE
    EndIf
EndFunc

Func _SetInterrupt()
    $interrupt = 1
    Sleep(3000)
EndFunc

;creates default .ini file
Func _CreateINI()
    IniWrite($ininame, $section, "InterruptKey", "{PAUSE}")
    IniWrite($ininame, $section, "ToolTipX", "")
    IniWrite($ininame, $section, "ToolTipY", "")
    IniWrite($ininame, $section, "TargetPath", "")
    IniWrite($ininame, $section, "ListPath", "")
    IniWrite($ininame, $section, "LogPath", "")
EndFunc

;writes line to log file
Func _WriteLog($msg)
    $fhandle = FileOpen($logpath, 9)
    FileWriteLine($fhandle, $msg)
    FileClose($fhandle)
EndFunc

;returns current date
Func _GetDate()
    Return @YEAR & "-" & @MON & "-" & @MDAY
EndFunc

;returns time of day
Func _GetTime()
    Return @HOUR & ":" & @MIN & ":" & @SEC
EndFunc

;converts milliseconds into Dd:HHh:MMm:SSs
Func _ConvertTime($millis)
    Local $days = Int($millis / 86400000)
    $millis -= $days * 86400000
    Local $hours = Int($millis / 3600000)
    $millis -= $hours * 3600000
    Local $minutes = Int($millis / 60000)
    $millis -= $minutes * 60000
    Local $seconds = Int($millis / 1000)
    $millis -= $seconds * 1000
    Local $result = ""
    If $days > 0 Then
        $result &= $days & "d:"
    EndIf
    If $hours > 0 Then
        $result &= StringFormat("%.2d", $hours) & "h:"
    EndIf
    If $minutes > 0 Then
        $result &= StringFormat("%.2d", $minutes) & "m:"
    EndIf
    If $seconds > 0 Then
        $result &= StringFormat("%.2d", $seconds) & "s"
    Else
        $result &= "00s"
    EndIf
    Return $result
EndFunc

Here's my working script that uses FileCopy and DirCopy:

#include <File.au3>
Opt("MustDeclareVars", 1)
Global $ininame = "_" & StringReplace(@ScriptName, ".exe", "") & ".ini"
Global $section = "Options"
If Not FileExists($ininame) Then
    MsgBox(0x2030, "Error", "No """ & $ininame & """! Writing empty .ini file.")
    _CreateINI()
    Exit
EndIf

Global $hotkey = IniRead($ininame, $section, "InterruptKey", "{PAUSE}")
Global $tooltipx = IniRead($ininame, $section, "ToolTipX", @DesktopWidth)
Global $tooltipy = IniRead($ininame, $section, "ToolTipY", @DesktopHeight)
Global $targetpath = IniRead($ininame, $section, "TargetPath", "Error")
Global $listpath = IniRead($ininame, $section, "ListPath", "Error")
Global $logpath = IniRead($ininame, $section, "LogPath", "Error")
Global $interrupt = 0
Global $pass = 0
Global $fail = 0
Global $fhandle = 0
Global $targets

If StringCompare($targetpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid TargetPath!")
    Exit
ElseIf StringCompare($listpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid ListPath!")
    Exit
ElseIf StringCompare($logpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid LogPath!")
    Exit
EndIf

If FileExists($targetpath) == 0 Then
    MsgBox(0x2000, "Error", "TargetPath does not exist!")
    Exit
ElseIf FileExists($listpath) == 0 Then
    MsgBox(0x2000, "Error", "ListPath does not exist!")
    Exit
EndIf
    
HotKeySet($hotkey, "_SetInterrupt")

If _FileReadToArray($listpath, $targets) Then
    Local $avgtime = 0
    Local $time = 0
    Local $start = TimerInit()
    Local $i
    _WriteLog("Starting Log: " & _GetDate() & " " & _GetTime())
    For $i = 1 To $targets[0]
        If $interrupt Then
            ExitLoop
        EndIf
        If $i <> 1 Then
            $avgtime = $time / ($i - 1)
        EndIf
        ToolTip("Copy To: " & $targets[$i] & @CRLF & "Started: " & _GetTime() & " Avg Time: " & _ConvertTime($avgtime), $tooltipx, $tooltipy, StringReplace(@ScriptName, ".exe", "") & " (" & $i & "/" & $targets[0] & ")" & " [P: " & $pass & " F: " & $fail & "]", 0, 4)
        If StringInStr(FileGetAttrib($targetpath), "D") Then
            If DirCopy($targetpath, $targets[$i], 1) Then
                _WriteLog("[" & _GetTime() & "] SUCCESS DIR COPY: " & $targets[$i])
                $pass += 1
            Else
                _WriteLog("[" & _GetTime() & "] " & @TAB & "FAILED DIR COPY: " & $targets[$i])
                $fail += 1
            EndIf
        Else
            If FileCopy($targetpath, $targets[$i], 9) Then
                _WriteLog("[" & _GetTime() & "] SUCCESS FILE COPY: " & $targets[$i])
                $pass += 1
            Else
                _WriteLog("[" & _GetTime() & "] " & @TAB & "FAILED FILE COPY: " & $targets[$i])
                $fail += 1
            EndIf
        EndIf
        $time = TimerDiff($start)
        ToolTip("")
    Next
Else
    MsgBox(0x2000, "Error", "Unable to generate targets list!")
EndIf

Func OnAutoItExit()
    _WriteLog("Ending Log: " & _GetDate() & " " & _GetTime() & " [P: " & $pass & " F: " & $fail & "]")
EndFunc

Func _SetInterrupt()
    $interrupt = 1
    _WriteLog("[" & _GetTime() & "] UPLOAD INTERRUPTED!!!")
    Tooltip("Please wait...", $tooltipx, $tooltipy, "Upload Interrupted", 0, 4)
    Sleep(3000)
EndFunc

Func _CreateINI()
    IniWrite($ininame, $section, "InterruptKey", "{PAUSE}")
    IniWrite($ininame, $section, "ToolTipX", "")
    IniWrite($ininame, $section, "ToolTipY", "")
    IniWrite($ininame, $section, "TargetPath", "")
    IniWrite($ininame, $section, "ListPath", "")
    IniWrite($ininame, $section, "LogPath", "")
EndFunc

Func _WriteLog($msg)
    $fhandle = FileOpen($logpath, 9)
    FileWriteLine($fhandle, $msg)
    FileClose($fhandle)
EndFunc

Func _GetDate()
    Return @YEAR & "-" & @MON & "-" & @MDAY
EndFunc

Func _GetTime()
    Return @HOUR & ":" & @MIN & ":" & @SEC
EndFunc

Func _ConvertTime($millis)
    Local $days = Int($millis / 86400000)
    $millis -= $days * 86400000
    Local $hours = Int($millis / 3600000)
    $millis -= $hours * 3600000
    Local $minutes = Int($millis / 60000)
    $millis -= $minutes * 60000
    Local $seconds = Int($millis / 1000)
    $millis -= $seconds * 1000
    Local $result = ""
    If $days > 0 Then
        $result &= $days & "d:"
    EndIf
    If $hours > 0 Then
        $result &= StringFormat("%.2d", $hours) & "h:"
    EndIf
    If $minutes > 0 Then
        $result &= StringFormat("%.2d", $minutes) & "m:"
    EndIf
    If $seconds > 0 Then
        $result &= StringFormat("%.2d", $seconds) & "s"
    Else
        $result &= "00s"
    EndIf
    Return $result
EndFunc

Contents of my input files are as follows...

_Upload_File2.ini (must have same name as compiled script)

[Options]
InterruptKey={PAUSE}
ToolTipX=1024
ToolTipY=675
TargetPath=D:\[Upload]\_Upload\W2K3_Patch\6_WindowsServer2003-KB923561-x86-ENU.exe
ListPath=servers.txt
LogPath=upload.txt

servers.txt

D:\[Upload]\_Upload\6_WindowsServer2003-KB923561-x86-ENU.exe
Edited by omikron48

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Tweaked your script a little to work locally for testing. This works for me:

#include <Constants.au3>
#include <File.au3>
#include <Misc.au3>
#include <WinAPIEx.au3>
Opt("MustDeclareVars", 1)

;Global $ininame = "_" & StringReplace(@ScriptName, ".exe", "") & ".ini"
Global $ininame = "_Upload_File2.ini"
Global $section = "Options"
;check if .ini file exists
If Not FileExists($ininame) Then
    MsgBox(0x2030, "Error", "No """ & $ininame & """! Writing empty .ini file.")
    _CreateINI()
    Exit
EndIf

Global $hotkey = IniRead($ininame, $section, "InterruptKey", "{PAUSE}")
Global $tooltipx = IniRead($ininame, $section, "ToolTipX", @DesktopWidth)
Global $tooltipy = IniRead($ininame, $section, "ToolTipY", @DesktopHeight)
Global $sourcepath = IniRead($ininame, $section, "sourcepath", "Error")
Global $listpath = IniRead($ininame, $section, "ListPath", "Error")
Global $logpath = IniRead($ininame, $section, "LogPath", "Error")
Global $interrupt = 0
Global $pass = 0
Global $fail = 0
Global $fhandle = 0
Global $targets
Global $title = ""
Global $text = ""
Global $target_drive, $target_dir

;check input in .ini file
If StringCompare($sourcepath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid sourcepath!")
    Exit
ElseIf StringCompare($listpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid ListPath!")
    Exit
ElseIf StringCompare($logpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid LogPath!")
    Exit
EndIf

;check that file/folder to be copied and list of copy locations exist
If FileExists($sourcepath) == 0 Then
    MsgBox(0x2000, "Error", "sourcepath does not exist!")
    Exit
ElseIf FileExists($listpath) == 0 Then
    MsgBox(0x2000, "Error", "ListPath does not exist!")
    Exit
EndIf

HotKeySet($hotkey, "_SetInterrupt")
Global $hProgressRoutine

;read list fo copy locations into array
If _FileReadToArray($listpath, $targets) Then
    Local $avgtime = 0
    Local $time = 0
    Local $start = TimerInit()
    Local $i
    _WriteLog("Starting Log: " & _GetDate() & " " & _GetTime())
    ;iterate for each copy location
    For $i = 1 To $targets[0]
        If $interrupt Then
            ExitLoop
        EndIf
        ;recalculate average after first upload
        If $i <> 1 Then
            $avgtime = $time / ($i - 1)
        EndIf
        ;for display purposes (currently unused)
        $title = StringReplace(@ScriptName, ".exe", "") & " (" & $i & "/" & $targets[0] & ")" & " [P: " & $pass & " F: " & $fail & "]"
        $text = "Copy To: " & $targets[$i] & @CRLF & "Started: " & _GetTime() & " Avg Time: " & _ConvertTime($avgtime)
        $target_dir = StringLeft($targets[$i],StringInStr($targets[$i],"\",0,-1))
        $target_drive = StringLeft($targets[$i],3)

        if FileExists($target_drive) Then
            If not FileExists($target_dir) Then
                DirCreate($target_dir)
            EndIf
        Else
            MsgBox(16, "Error", "Target Drive not found!")
        endif
        $hProgressRoutine = DllCallbackRegister('_Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;ptr')
        If _WinAPI_CopyFileEx(FileGetShortName($sourcepath), FileGetShortName($targets[$i]), DllCallbackGetPtr($hProgressRoutine)) Then
            _WriteLog("[" & _GetTime() & "] SUCCESS FILE COPY: " & $targets[$i])
            $pass += 1
        Else
            _WriteLog("[" & _GetTime() & "] " & @TAB & "FAILED FILE COPY: " & $targets[$i])
            $fail += 1
        EndIf
        DllCallbackFree($hProgressRoutine)
        $time = TimerDiff($start)
    Next
Else
    MsgBox(0x2000, "Error", "Unable to generate targets list!")
EndIf

;called on script close
Func OnAutoItExit()
    _WriteLog("Ending Log: " & _GetDate() & " " & _GetTime() & " [P: " & $pass & " F: " & $fail & "]")
EndFunc   ;==>OnAutoItExit

Func _Progress($iTotalFileSize, $iTotalBytesTransferred, $iStreamSize, $iStreamBytesTransferred, $iStreamNumber, $iCallbackReason, $hSourceFile, $hDestinationFile, $iData)
    If $interrupt == 1 Then
        _WriteLog("[" & _GetTime() & "] UPLOAD INTERRUPTED!!!")
        Return $PROGRESS_CANCEL
    Else
        _WriteLog("[" & _GetTime() & "] " & $iTotalFileSize & " / " & $iTotalBytesTransferred)
        Return $PROGRESS_CONTINUE
    EndIf
EndFunc   ;==>_Progress

Func _SetInterrupt()
    $interrupt = 1
    Sleep(3000)
EndFunc   ;==>_SetInterrupt

;creates default .ini file
Func _CreateINI()
    IniWrite($ininame, $section, "InterruptKey", "{PAUSE}")
    IniWrite($ininame, $section, "ToolTipX", "")
    IniWrite($ininame, $section, "ToolTipY", "")
    IniWrite($ininame, $section, "sourcepath", "")
    IniWrite($ininame, $section, "ListPath", "")
    IniWrite($ininame, $section, "LogPath", "")
EndFunc   ;==>_CreateINI

;writes line to log file
Func _WriteLog($msg)
    $fhandle = FileOpen($logpath, 9)
    FileWriteLine($fhandle, $msg)
    FileClose($fhandle)
EndFunc   ;==>_WriteLog

;returns current date
Func _GetDate()
    Return @YEAR & "-" & @MON & "-" & @MDAY
EndFunc   ;==>_GetDate

;returns time of day
Func _GetTime()
    Return @HOUR & ":" & @MIN & ":" & @SEC
EndFunc   ;==>_GetTime

;converts milliseconds into Dd:HHh:MMm:SSs
Func _ConvertTime($millis)
    Local $days = Int($millis / 86400000)
    $millis -= $days * 86400000
    Local $hours = Int($millis / 3600000)
    $millis -= $hours * 3600000
    Local $minutes = Int($millis / 60000)
    $millis -= $minutes * 60000
    Local $seconds = Int($millis / 1000)
    $millis -= $seconds * 1000
    Local $result = ""
    If $days > 0 Then
        $result &= $days & "d:"
    EndIf
    If $hours > 0 Then
        $result &= StringFormat("%.2d", $hours) & "h:"
    EndIf
    If $minutes > 0 Then
        $result &= StringFormat("%.2d", $minutes) & "m:"
    EndIf
    If $seconds > 0 Then
        $result &= StringFormat("%.2d", $seconds) & "s"
    Else
        $result &= "00s"
    EndIf
    Return $result
EndFunc   ;==>_ConvertTime

Maybe you should comment this line out:

_WriteLog("[" & _GetTime() & "] " & $iTotalFileSize & " / " & $iTotalBytesTransferred)

and for testing I hardcoded the ini name to _Upload_File2.ini

Servers.txt:

C:\temp\_test\[upload]\autoit-v3-setup.exe

_Upload_File2.ini:

[Options]

InterruptKey={PAUSE}

ToolTipX=1024

ToolTipY=675

sourcepath=C:\temp\_test\autoit-v3-setup.exe

ListPath=servers.txt

LogPath=upload.txt

Edited by KaFu

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

I got it working, somewhat...

The only problem is that it only supports single file copies and not directory copies. The only thing that's improved is I now have a progress indicator.

It seems I can't set a hotkey to toggle a flag to interrupt CopyFileEx. I would like to be able to set different hotkeys since I run multiple instances of my script at a time, up to 10 at times. Yashied's sample uses _IsPressed but it would be harder to set from an .ini file since _IsPressed uses key values and not strings. I also need to figure out a way to adjust the progress indicator to track progress on transfer of a whole directory while using CopyFileEx and DirCreate recursively on its contents.

In any case, here's the working script I got so far. I re-included the information display.

#include <File.au3>
#include <WinAPIEx.au3>
Opt("MustDeclareVars", 1)
OnAutoItExitRegister("_OnClose")

Global $scriptname = StringReplace(@ScriptName, ".exe", "")
Global $ininame = "_" & $scriptname & ".ini"
Global $section = "Options"
;check if .ini file exists
If Not FileExists($ininame) Then
    MsgBox(0x2030, "Error", "No """ & $ininame & """! Writing empty .ini file.")
    _CreateINI()
    Exit
EndIf

Global $hotkey = IniRead($ininame, $section, "InterruptKey", "{PAUSE}")
Global $tooltipx = IniRead($ininame, $section, "ToolTipX", @DesktopWidth)
Global $tooltipy = IniRead($ininame, $section, "ToolTipY", @DesktopHeight)
Global $sourcepath = IniRead($ininame, $section, "SourcePath", "Error")
Global $listpath = IniRead($ininame, $section, "ListPath", "Error")
Global $logpath = IniRead($ininame, $section, "LogPath", "Error")
Global $interrupt = 0
Global $pass = 0
Global $fail = 0
Global $fhandle = 0
Global $targets
Global $targetdrive
Global $targetdir
Global $title = ""
Global $text = ""

;check input in .ini file
If StringCompare($sourcepath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid SourcePath!")
    Exit
ElseIf StringCompare($listpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid ListPath!")
    Exit
ElseIf StringCompare($logpath, "Error") == 0 Then
    MsgBox(0x2000, "Error", "Invalid LogPath!")
    Exit
EndIf

;check that file/folder to be copied and list of copy locations exist
If FileExists($sourcepath) == 0 Then
    MsgBox(0x2000, "Error", "TargetPath does not exist!")
    Exit
ElseIf FileExists($listpath) == 0 Then
    MsgBox(0x2000, "Error", "ListPath does not exist!")
    Exit
EndIf

HotKeySet($hotkey, "_SetInterrupt")
Global $hProgressRoutine

;read list fo copy locations into array
If _FileReadToArray($listpath, $targets) Then
    Local $avgtime = 0
    Local $time = 0
    Local $start = TimerInit()
    Local $i
    _WriteLog("Starting Log: " & _GetDate() & " " & _GetTime())
    ;iterate for each copy location
    For $i = 1 To $targets[0]
        If $interrupt Then
            ExitLoop
        EndIf
        ;recalculate average after first upload
        If $i <> 1 Then
            $avgtime = $time / ($i - 1)
        EndIf
        $targetdir = StringLeft($targets[$i], StringInStr($targets[$i], "\", 0, -1))
;       If StringCompare(StringLeft($targets[$i], 2), "\\") == 0 Then
;           $targetdrive = StringLeft($targets[$i], StringInStr($targets[$i], "\", 0, 3) - 1)
;       Else
;           $targetdrive = StringLeft($targets[$i], 3)
;       EndIf
        If Not FileExists($targetdir) Then
            If Not DirCreate($targetdir) Then
                _WriteLog("[" & _GetTime() & "] " & @TAB & "UNABLE TO CREATE: " & $targetdir)
                ContinueLoop
            EndIf
        EndIf
        ;for display purposes (currently unused)
        $title = $scriptname & " (" & $i & "/" & $targets[0] & ")" & " [P: " & $pass & " F: " & $fail & "]"
        $text = "Copy To: " & $targets[$i] & @CRLF & "Started: " & _GetTime() & " Avg Time: " & _ConvertTime($avgtime)
        $hProgressRoutine = DllCallbackRegister('_Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;ptr')
        ToolTip($text, $tooltipx, $tooltipy, $title)
        If _WinAPI_CopyFileEx($sourcepath, $targets[$i],  DllCallBackGetPtr($hProgressRoutine)) Then
            _WriteLog("[" & _GetTime() & "] SUCCESS FILE COPY: " & $targets[$i])
            $pass += 1
        Else
            _WriteLog("[" & _GetTime() & "] " & @TAB & "FAILED FILE COPY: " & $targets[$i])
            $fail += 1
        EndIf
        DllCallbackFree($hProgressRoutine)
        $time = TimerDiff($start)
        ToolTip("")
    Next
Else
    MsgBox(0x2000, "Error", "Unable to generate targets list!")
EndIf

;called on script close
Func _OnClose()
    _WriteLog("Ending Log: " & _GetDate() & " " & _GetTime() & " [P: " & $pass & " F: " & $fail & "]")
EndFunc

Func _Progress($iTotalFileSize, $iTotalBytesTransferred, $iStreamSize, $iStreamBytesTransferred, $iStreamNumber, $iCallbackReason, $hSourceFile, $hDestinationFile, $iData)
    ToolTip($text & " Progress: " & Round($iTotalBytesTransferred / $iTotalFileSize * 100, 1) & '%', $tooltipx, $tooltipy, $title, 0 ,4)
    If $interrupt == 1 Then
        _WriteLog("[" & _GetTime() & "] UPLOAD INTERRUPTED!!!")
        Return $PROGRESS_CANCEL
    Else
        Return $PROGRESS_CONTINUE
    EndIf
EndFunc

Func _SetInterrupt()
    $interrupt = 1
EndFunc

;creates default .ini file
Func _CreateINI()
    IniWrite($ininame, $section, "InterruptKey", "{PAUSE}")
    IniWrite($ininame, $section, "ToolTipX", "")
    IniWrite($ininame, $section, "ToolTipY", "")
    IniWrite($ininame, $section, "SourcePath", "")
    IniWrite($ininame, $section, "ListPath", "")
    IniWrite($ininame, $section, "LogPath", "")
EndFunc

;writes line to log file
Func _WriteLog($msg)
    $fhandle = FileOpen($logpath, 9)
    FileWriteLine($fhandle, $msg)
    FileClose($fhandle)
EndFunc

;returns current date
Func _GetDate()
    Return @YEAR & "-" & @MON & "-" & @MDAY
EndFunc

;returns time of day
Func _GetTime()
    Return @HOUR & ":" & @MIN & ":" & @SEC
EndFunc

;converts milliseconds into Dd:HHh:MMm:SSs
Func _ConvertTime($millis)
    Local $days = Int($millis / 86400000)
    $millis -= $days * 86400000
    Local $hours = Int($millis / 3600000)
    $millis -= $hours * 3600000
    Local $minutes = Int($millis / 60000)
    $millis -= $minutes * 60000
    Local $seconds = Int($millis / 1000)
    $millis -= $seconds * 1000
    Local $result = ""
    If $days > 0 Then
        $result &= $days & "d:"
    EndIf
    If $hours > 0 Then
        $result &= StringFormat("%.2d", $hours) & "h:"
    EndIf
    If $minutes > 0 Then
        $result &= StringFormat("%.2d", $minutes) & "m:"
    EndIf
    If $seconds > 0 Then
        $result &= StringFormat("%.2d", $seconds) & "s"
    Else
        $result &= "00s"
    EndIf
    Return $result
EndFunc
Edited by omikron48

Share this post


Link to post
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
Sign in to follow this  
Followers 0