Jump to content

GUI twitching/stuttering


llewxam
 Share

Recommended Posts

Sorry for the huge example script...

When any given file crosses about the 100MB in a transfer Vista and 7 both have an odd twitch and all controls die until the file has finished copying. Under XP the controls die at the same time, but there is no twitch to the GUI. Anybody have any thoughts as to why? Also looking for suggestions to keep the progressbars in sync properly under Vista/7.

Thanks

Ian

#include <WindowsConstants.au3> ;needed for $WS_EX_ACCEPTFILES, $DT_END_ELLIPSIS
#include <EditConstants.au3> ;needed for $ES_READONLY
#include <GUIConstantsEx.au3> ;needed for $GUI_DROPACCEPTED, $GUI_HIDE, $GUI_EVENT_CLOSE, $GUI_SHOW, $GUI_UNCHECKED
#include <String.au3> ;needed for _StringAddThousandsSep

$main=GUICreate("Sync 2 Build 4",550,400,1,1,-1,$WS_EX_ACCEPTFILES)
$instructions=GUICtrlCreateLabel("Browse left, type path, or drag and drop",60,5,300,20)
GUICtrlCreateLabel("Total Files",400,5,100,20)
$totalfileslabel=GUICtrlCreateInput("",400,25,100,20,$ES_READONLY)
GUICtrlCreateLabel("Total Size",400,45,100,20)
$totalsizelabel=GUICtrlCreateInput("",400,65,100,20,$ES_READONLY)
$sourcebtn=GUICtrlCreateButton("Source",5,25,50,20)
$targetbtn=GUICtrlCreateButton("Target",5,65,50,20)
$addbtn=GUICtrlCreateButton("Add",315,65,50,20)
$startbtn=GUICtrlCreateButton("START",485,135,60,20)
$sourceinput=GUICtrlCreateInput("",60,25,250,20)
$targetinput=GUICtrlCreateInput("",60,65,250,20)
$job=GUICtrlCreateList("",5,160,540,215,$ES_READONLY)
GUICtrlSetState($sourceinput,$GUI_DROPACCEPTED)
GUICtrlSetState($targetinput,$GUI_DROPACCEPTED)
GUICtrlSetState($startbtn,$GUI_HIDE)
GUISetState(@SW_SHOW,$main)
ControlFocus("","",$sourceinput)

dim $accelkeys[1][2]=[["{ENTER}",$addbtn]]
GUISetAccelerators($accelkeys)

Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') ;used in..........
Local $ptr = DllCallbackGetPtr($callback) ;............... _CopyWithProgress
local $size ;size of task (dir or single file)
local $count ;used to help with padding in the listbox
local $fill ;the spacing for above
local $queue ;the list of what is being copied (all tasks)
local $totalfiles ;total number of files to be copied
local $totalsize ;total byte count of files
local $donesofar ;total bytes copied so far
local $bytes ;used as placeholder in __Progress
local $failedfiles ;string of failed copies
local $failed ;count of failures

Do
    $msg=GUIGetMsg()
    if $msg=$GUI_EVENT_CLOSE then Exit
        
    if $msg=$sourcebtn then GUICtrlSetData($sourceinput,FileSelectFolder("Select a folder",""))

    if $msg=$targetbtn then GUICtrlSetData($targetinput,FileSelectFolder("Select a folder","",1))
        
    if $msg=$addbtn Then
        $source=GUICtrlRead($sourceinput)
        $target=GUICtrlRead($targetinput)
        if not FileExists($target) then DirCreate($target)
        if FileExists($source) and FileExists($target) Then
            $wait=GUICtrlCreateLabel("Please wait, files are being enumerated",100,100,400,20)

            If StringInStr(FileGetAttrib($source), "D") > 0 Then
                $count+=1
                for $padding=1 to $count
                    $fill&=" "
                Next            
                $sourceinfo=DirGetSize($source,1)
                GUICtrlSetData($job,$source&" -> "&$target)
                GUICtrlSetData($job,"("&_StringAddThousandsSep($sourceinfo[1])&" files "&_StringAddThousandsSep(round($sourceinfo[0]/1000000,2))&"MB)")
                GUICtrlSetData($job,$fill)
                $size+=$sourceinfo[0]
                $totalfiles+=$sourceinfo[1]
                $totalsize+=$sourceinfo[0]
                $queue&=$source&chr(1)&$target&chr(1)&"D"&chr(1)
                GUICtrlSetData($sourceinput,"")
                GUICtrlSetData($targetinput,"")
                GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
                GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
                GUICtrlDelete($wait)
                ControlFocus("","",$sourceinput)
                GUICtrlSetState($startbtn,$GUI_SHOW)
            Else
                $count+=1
                for $padding=1 to $count
                    $fill&=" "
                Next            
                $sourceinfo=FileGetSize($source)
                GUICtrlSetData($job,$source&" -> "&$target)
                GUICtrlSetData($job,"(1 file "&_StringAddThousandsSep(round($sourceinfo/1000000,2))&"MB)")
                GUICtrlSetData($job,$fill)
                $size+=$sourceinfo
                $totalfiles+=1
                $totalsize+=$sourceinfo
                $queue&=$source&chr(1)&$target&chr(1)&"F"&chr(1)
                GUICtrlSetData($sourceinput,"")
                GUICtrlSetData($targetinput,"")
                GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
                GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
                GUICtrlDelete($wait)
                ControlFocus("","",$sourceinput)
                GUICtrlSetState($startbtn,$GUI_SHOW)
            EndIf
        Else
            msgbox(0,"Error","Please check your source and target paths")           
        EndIf
    EndIf ;end $addbtn
    
    if $msg=$startbtn Then
        $display=TimerInit()
        $howlong=TimerInit()
        GUICtrlDelete($startbtn)
        GUICtrlDelete($instructions)
        ControlDisable("","",$sourcebtn)
        ControlDisable("","",$targetbtn)
        ControlDisable("","",$addbtn)
        ControlDisable("","",$startbtn)
        ControlDisable("","",$sourceinput)
        ControlDisable("","",$targetinput)
        ControlDisable("","",$job)
        $fileslide=GUICtrlCreateProgress(5,375,265,20)
        $totalslide=GUICtrlCreateProgress(280,375,265,20)
        $stop=GUICtrlCreateCheckbox("STOP",495,135,60,20)
        $showfilename=GUICtrlCreateLabel("",10,100,530,20,$DT_END_ELLIPSIS)
        GUICtrlCreateLabel("Overall progress - ",10,125,430,20)
        $showtotalprog=GUICtrlCreateLabel("",96,125,230,20)
        $breaksources=StringSplit($queue,chr(1))
        for $doit=1 to ($breaksources[0]-1) step 3
            if $breaksources[$doit+2]="D" then 
                $basedir=$breaksources[$doit]
                $target=$breaksources[$doit+1]
                $baselen = StringLen($basedir)
                theheart($basedir)
            EndIf
            if $breaksources[$doit+2]="F" then 
                $source=$breaksources[$doit]
                $target=$breaksources[$doit+1]
                $name=StringTrimLeft($source,StringInStr($source,"\",0,-1))
                $copied = _CopyWithProgress($source,$target&"\"&$name)
                if $copied=0 then 
                    $failed+=1
                    $failedfiles&=$source&chr(2)
                    $lastbyte=0
                    $bytes=0
                EndIf
            EndIf
        Next
        GUICtrlSetData($showfilename,"")
        $totaltimetorun=TimerDiff($howlong)
        $minutes=round($totaltimetorun/60000,2)
        if $failed=0 then msgbox(0,"Finished in "&$minutes&" minutes","Finished with no errors")
        if $failed<>0 then
            $yesorno=msgbox(4,"Finished in "&$minutes&" minutes","Finished with "&$failed&" errors, do you want to see the failed files?")
            if $yesorno=6 then
                $failedwindow=GUICreate("Failed Files",@DesktopWidth,300) ;to display the failed files
                $failedlist=GUICtrlCreateList("",5,5,@DesktopWidth-10,290) ;to display the failed files
                GUISetState(@sw_show,$failedwindow) ;done setting up GUI
                StringTrimRight($failedfiles,1) ;take off the trailing delimeter
                $failedarray=StringSplit($failedfiles,chr(2)) ;break up the list of failed files
                for $show=1 to $failedarray[0]-1
                    GUICtrlSetData($failedlist,$failedarray[$show]) ;list the failed files
                Next
                Do
                    $msg=GUIGetMsg()
                    if $msg=$GUI_EVENT_CLOSE then exit ;when the failed window is closed, quit the program
                until 1=2
            EndIf
        EndIf
        Exit
    EndIf ;end $startbtn
until 1=2


Func theheart($basedir)

    While GUICtrlRead($stop) == 1 ;look for the pause button
        $quit=msgbox(36,"Paused","Quit Now?")
        if $quit=6 then exit ;yes
        if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
    WEnd
    $basesearch = FileFindFirstFile($basedir & "\*.*")
    If $basesearch == -1 Then Return 0 ; specified folder is empty!
    While @error <> 1
        $basefile = FileFindNextFile($basesearch)
        ; skip these
        If $basefile == "." Or $basefile == ".." Or $basefile == "" Then
            ContinueLoop
        EndIf
        ; if it's a dir then call this function again (nesting the function is clever ;)
        $formattedfile = $basedir & "\" & $basefile
        If StringInStr(FileGetAttrib($formattedfile), "D") > 0 Then
            theheart($formattedfile)
        Else
            ; Files we need to deal with
            $dest=StringTrimLeft($formattedfile,$baselen)
                    
            While GUICtrlRead($stop) == 1 ;look for the pause button
                $quit=msgbox(36,"Paused","Quit Now?")
                if $quit=6 then exit ;yes
                if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
            WEnd
            GUICtrlSetData($showfilename,$formattedfile);&" - "&$BytesTransferred / $FileSize * 100&"%")
            if not FileExists($target&$dest) then 
                $copied = _CopyWithProgress($formattedfile,$target&"\"&$dest)
                if $copied=0 then 
                    $failed+=1
                    $failedfiles&=$formattedfile&chr(2)
                EndIf
            Else
                $donesofar+=FileGetSize($formattedfile)
                GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
                GUICtrlSetData($totalslide,$donesofar / $size * 100)
            EndIf
            $lastbyte=0
            $bytes=0
        endif
    WEnd
    FileClose($basesearch)
    Return 1

EndFunc ;end theheart


Func _CopyWithProgress($inSource, $inDest)
    
; Function to copy a file showing a realtime progress bar
;
; By Paul Niven (NiVZ)
;
; 05/11/2008
;
; Parameters:
;
; $inSource  -   Full path to source file
; $inDest   -    Full path to destination file (structure will be created if it does not exist
;
; Returns 0 if copy is successful and 1 if it fails
;
;
; Updates:
;
; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying
;           - Now uses Kernal32 and DllCallBackRegister to provide faster copying
;             Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3
;             See: http://www.autoit.de/index.php?page=Thread&postID=58875
      
    $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1))

    If Not FileExists($DestDir) Then DirCreate($DestDir)
    
    $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0)

    If $ret[0] <> 0 Then
    ; Success
        Return 1
    Else
    ; Fail
        Return 0
    EndIf
    
EndFunc


Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)

    $lastbyte=$bytes
    $bytes=$BytesTransferred
    $bytediff=$bytes-$lastbyte
    $donesofar+=$bytediff
    GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
    GUICtrlSetData($totalslide,$donesofar / $size * 100)
    GUICtrlSetData($fileslide,$BytesTransferred / $FileSize * 100)

EndFunc

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

I would guess that once you start copying the script is hung up waiting for the copy to finish and it cannot respond to events.

I would first try using OnEvent mode. Set a flag in the function for the start button and return from that function, then detect the flag in your main idle loop and call the copy function so that other events can be processed while the copying is done.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I would guess that once you start copying the script is hung up waiting for the copy to finish and it cannot respond to events.

I would first try using OnEvent mode. Set a flag in the function for the start button and return from that function, then detect the flag in your main idle loop and call the copy function so that other events can be processed while the copying is done.

Whew, hehehe won't lie to ya, the concept makes sense but I've never used OnEvent before, I'll look in to it and post back if I can get it going, thanks!

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

hmmmm, same thing. I am not quite sure what you meant by "return from that function, then detect the flag in your main idle loop and call the copy function", could you explain it differently maybe? I searched for GUIOnEventMode but didn't see anything like what you described in the first page.....

Thanks

Ian

#include <WindowsConstants.au3> ;needed for $WS_EX_ACCEPTFILES, $DT_END_ELLIPSIS
#include <EditConstants.au3> ;needed for $ES_READONLY
#include <GUIConstantsEx.au3> ;needed for $GUI_DROPACCEPTED, $GUI_HIDE, $GUI_EVENT_CLOSE, $GUI_SHOW, $GUI_UNCHECKED
#include <String.au3> ;needed for _StringAddThousandsSep
Opt("GUIOnEventMode", 1)


$main=GUICreate("Sync 2 Build 4",550,400,1,1,-1,$WS_EX_ACCEPTFILES)
GUISetOnEvent($GUI_EVENT_CLOSE, "close")
$instructions=GUICtrlCreateLabel("Browse left, type path, or drag and drop",60,5,300,20)
GUICtrlCreateLabel("Total Files",400,5,100,20)
$totalfileslabel=GUICtrlCreateInput("",400,25,100,20,$ES_READONLY)
GUICtrlCreateLabel("Total Size",400,45,100,20)
$totalsizelabel=GUICtrlCreateInput("",400,65,100,20,$ES_READONLY)
$sourcebtn=GUICtrlCreateButton("Source",5,25,50,20)
GUICtrlSetOnEvent($sourcebtn, "source")
$targetbtn=GUICtrlCreateButton("Target",5,65,50,20)
GUICtrlSetOnEvent($targetbtn, "target")
$addbtn=GUICtrlCreateButton("Add",315,65,50,20)
GUICtrlSetOnEvent($addbtn, "addbtn")
$startbtn=GUICtrlCreateButton("START",485,135,60,20)
GUICtrlSetOnEvent($startbtn, "startbtn")
$sourceinput=GUICtrlCreateInput("",60,25,250,20)
$targetinput=GUICtrlCreateInput("",60,65,250,20)
$job=GUICtrlCreateList("",5,160,540,215,$ES_READONLY)
GUICtrlSetState($sourceinput,$GUI_DROPACCEPTED)
GUICtrlSetState($targetinput,$GUI_DROPACCEPTED)
GUICtrlSetState($startbtn,$GUI_HIDE)
GUISetState(@SW_SHOW,$main)
ControlFocus("","",$sourceinput)

dim $accelkeys[1][2]=[["{ENTER}",$addbtn]]
GUISetAccelerators($accelkeys)

Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') ;used in..........
Local $ptr = DllCallbackGetPtr($callback) ;............... _CopyWithProgress
local $size ;size of task (dir or single file)
local $count ;used to help with padding in the listbox
local $fill ;the spacing for above
local $queue ;the list of what is being copied (all tasks)
local $totalfiles ;total number of files to be copied
local $totalsize ;total byte count of files
local $donesofar ;total bytes copied so far
local $bytes ;used as placeholder in __Progress
local $failedfiles ;string of failed copies
local $failed ;count of failures
local $stop, $baselen, $showfilename, $showtotalprog, $totalslide, $fileslide, $target

Do
    sleep(1000)
until 1=2

func source()
    GUICtrlSetData($sourceinput,FileSelectFolder("Select a folder",""))
EndFunc

func target()
    GUICtrlSetData($targetinput,FileSelectFolder("Select a folder","",1))
EndFunc

func close()
    Exit
EndFunc

func addbtn()
    $source=GUICtrlRead($sourceinput)
    $target=GUICtrlRead($targetinput)
    if not FileExists($target) then DirCreate($target)
    if FileExists($source) and FileExists($target) Then
        $wait=GUICtrlCreateLabel("Please wait, files are being enumerated",100,100,400,20)
        If StringInStr(FileGetAttrib($source), "D") > 0 Then
            $count+=1
            for $padding=1 to $count
                $fill&=" "
            Next            
            $sourceinfo=DirGetSize($source,1)
            GUICtrlSetData($job,$source&" -> "&$target)
            GUICtrlSetData($job,"("&_StringAddThousandsSep($sourceinfo[1])&" files "&_StringAddThousandsSep(round($sourceinfo[0]/1000000,2))&"MB)")
            GUICtrlSetData($job,$fill)
            $size+=$sourceinfo[0]
            $totalfiles+=$sourceinfo[1]
            $totalsize+=$sourceinfo[0]
            $queue&=$source&chr(1)&$target&chr(1)&"D"&chr(1)
            GUICtrlSetData($sourceinput,"")
            GUICtrlSetData($targetinput,"")
            GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
            GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
            GUICtrlDelete($wait)
            ControlFocus("","",$sourceinput)
            GUICtrlSetState($startbtn,$GUI_SHOW)
        Else
            $count+=1
            for $padding=1 to $count
                $fill&=" "
            Next            
            $sourceinfo=FileGetSize($source)
            GUICtrlSetData($job,$source&" -> "&$target)
            GUICtrlSetData($job,"(1 file "&_StringAddThousandsSep(round($sourceinfo/1000000,2))&"MB)")
            GUICtrlSetData($job,$fill)
            $size+=$sourceinfo
            $totalfiles+=1
            $totalsize+=$sourceinfo
            $queue&=$source&chr(1)&$target&chr(1)&"F"&chr(1)
            GUICtrlSetData($sourceinput,"")
            GUICtrlSetData($targetinput,"")
            GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
            GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
            GUICtrlDelete($wait)
            ControlFocus("","",$sourceinput)
            GUICtrlSetState($startbtn,$GUI_SHOW)
        EndIf
    Else
        msgbox(0,"Error","Please check your source and target paths")           
    EndIf
EndFunc

func startbtn()
    $display=TimerInit()
    $howlong=TimerInit()
    GUICtrlDelete($startbtn)
    GUICtrlDelete($instructions)
    ControlDisable("","",$sourcebtn)
    ControlDisable("","",$targetbtn)
    ControlDisable("","",$addbtn)
    ControlDisable("","",$startbtn)
    ControlDisable("","",$sourceinput)
    ControlDisable("","",$targetinput)
    ControlDisable("","",$job)
    $fileslide=GUICtrlCreateProgress(5,375,265,20)
    $totalslide=GUICtrlCreateProgress(280,375,265,20)
    $stop=GUICtrlCreateCheckbox("STOP",495,135,60,20)
    $showfilename=GUICtrlCreateLabel("",10,100,530,20,$DT_END_ELLIPSIS)
    GUICtrlCreateLabel("Overall progress - ",10,125,430,20)
    $showtotalprog=GUICtrlCreateLabel("",96,125,230,20)
    $breaksources=StringSplit($queue,chr(1))
    for $doit=1 to ($breaksources[0]-1) step 3
        if $breaksources[$doit+2]="D" then 
            $basedir=$breaksources[$doit]
            $target=$breaksources[$doit+1]
            $baselen = StringLen($basedir)
            theheart($basedir)
        EndIf
        if $breaksources[$doit+2]="F" then 
            $source=$breaksources[$doit]
            $target=$breaksources[$doit+1]
            $name=StringTrimLeft($source,StringInStr($source,"\",0,-1))
            $copied = _CopyWithProgress($source,$target&"\"&$name)
            if $copied=0 then 
                $failed+=1
                $failedfiles&=$source&chr(2)
                $lastbyte=0
                $bytes=0
            EndIf
        EndIf
    Next
    GUICtrlSetData($showfilename,"")
    $totaltimetorun=TimerDiff($howlong)
    $minutes=round($totaltimetorun/60000,2)
    if $failed=0 then msgbox(0,"Finished in "&$minutes&" minutes","Finished with no errors")
    if $failed<>0 then
        $yesorno=msgbox(4,"Finished in "&$minutes&" minutes","Finished with "&$failed&" errors, do you want to see the failed files?")
        if $yesorno=6 then
            $failedwindow=GUICreate("Failed Files",@DesktopWidth,300) ;to display the failed files
            $failedlist=GUICtrlCreateList("",5,5,@DesktopWidth-10,290) ;to display the failed files
            GUISetState(@sw_show,$failedwindow) ;done setting up GUI
            StringTrimRight($failedfiles,1) ;take off the trailing delimeter
            $failedarray=StringSplit($failedfiles,chr(2)) ;break up the list of failed files
            for $show=1 to $failedarray[0]-1
                GUICtrlSetData($failedlist,$failedarray[$show]) ;list the failed files
            Next
            Do
                $msg=GUIGetMsg()
                if $msg=$GUI_EVENT_CLOSE then exit ;when the failed window is closed, quit the program
            until 1=2
        EndIf
    EndIf
    Exit
EndFunc

Func theheart($basedir)

    While GUICtrlRead($stop) == 1 ;look for the pause button
        $quit=msgbox(36,"Paused","Quit Now?")
        if $quit=6 then exit ;yes
        if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
    WEnd
    $basesearch = FileFindFirstFile($basedir & "\*.*")
    If $basesearch == -1 Then Return 0 ; specified folder is empty!
    While @error <> 1
        $basefile = FileFindNextFile($basesearch)
        ; skip these
        If $basefile == "." Or $basefile == ".." Or $basefile == "" Then
            ContinueLoop
        EndIf
        ; if it's a dir then call this function again (nesting the function is clever ;)
        $formattedfile = $basedir & "\" & $basefile
        If StringInStr(FileGetAttrib($formattedfile), "D") > 0 Then
            theheart($formattedfile)
        Else
            ; Files we need to deal with
            $dest=StringTrimLeft($formattedfile,$baselen)
                    
            While GUICtrlRead($stop) == 1 ;look for the pause button
                $quit=msgbox(36,"Paused","Quit Now?")
                if $quit=6 then exit ;yes
                if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
            WEnd
            GUICtrlSetData($showfilename,$formattedfile);&" - "&$BytesTransferred / $FileSize * 100&"%")
            if not FileExists($target&$dest) then 
                $copied = _CopyWithProgress($formattedfile,$target&"\"&$dest)
                if $copied=0 then 
                    $failed+=1
                    $failedfiles&=$formattedfile&chr(2)
                EndIf
            Else
                $donesofar+=FileGetSize($formattedfile)
                GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
                GUICtrlSetData($totalslide,$donesofar / $size * 100)
            EndIf
            $lastbyte=0
            $bytes=0
        endif
    WEnd
    FileClose($basesearch)
    Return 1

EndFunc ;end theheart


Func _CopyWithProgress($inSource, $inDest)
    
; Function to copy a file showing a realtime progress bar
;
; By Paul Niven (NiVZ)
;
; 05/11/2008
;
; Parameters:
;
; $inSource  -   Full path to source file
; $inDest   -    Full path to destination file (structure will be created if it does not exist
;
; Returns 0 if copy is successful and 1 if it fails
;
;
; Updates:
;
; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying
;           - Now uses Kernal32 and DllCallBackRegister to provide faster copying
;             Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3
;             See: http://www.autoit.de/index.php?page=Thread&postID=58875
      
    $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1))

    If Not FileExists($DestDir) Then DirCreate($DestDir)
    
    $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0)

    If $ret[0] <> 0 Then
    ; Success
        Return 1
    Else
    ; Fail
        Return 0
    EndIf
    
EndFunc


Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)

    $lastbyte=$bytes
    $bytes=$BytesTransferred
    $bytediff=$bytes-$lastbyte
    $donesofar+=$bytediff
    GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
    GUICtrlSetData($totalslide,$donesofar / $size * 100)
    GUICtrlSetData($fileslide,$BytesTransferred / $FileSize * 100)

EndFunc

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

hmmmm, same thing. I am not quite sure what you meant by "return from that function, then detect the flag in your main idle loop and call the copy function", could you explain it differently maybe? I searched for GUIOnEventMode but didn't see anything like what you described in the first page.....

Thanks

Ian

When you use OnEventmode you have functions set to be called when an event is fired. (I know you know that.) But only one function can be run at a time if that function is called in response to an event. So if you have a function which takes a long time to execute then all the events will get queued up and you can get problems. So with your function just set a flag and that's all. In your idle loop add a condition to see if the flag is set and if so call the real function which will take a long time. Now the function isn't directly running from an event and it can be interupted by other events. Of course the functions that these other events calls must not take too long or you will be back to the same problem.

I made the changes to your code and I haven't checked or tested it. As you will see it's very simple.

#include <WindowsConstants.au3> ;needed for $WS_EX_ACCEPTFILES, $DT_END_ELLIPSIS
#include <EditConstants.au3> ;needed for $ES_READONLY
#include <GUIConstantsEx.au3> ;needed for $GUI_DROPACCEPTED, $GUI_HIDE, $GUI_EVENT_CLOSE, $GUI_SHOW, $GUI_UNCHECKED
#include <String.au3> ;needed for _StringAddThousandsSep
Opt("GUIOnEventMode", 1)


$main=GUICreate("Sync 2 Build 4",550,400,1,1,-1,$WS_EX_ACCEPTFILES)
GUISetOnEvent($GUI_EVENT_CLOSE, "close")
$instructions=GUICtrlCreateLabel("Browse left, type path, or drag and drop",60,5,300,20)
GUICtrlCreateLabel("Total Files",400,5,100,20)
$totalfileslabel=GUICtrlCreateInput("",400,25,100,20,$ES_READONLY)
GUICtrlCreateLabel("Total Size",400,45,100,20)
$totalsizelabel=GUICtrlCreateInput("",400,65,100,20,$ES_READONLY)
$sourcebtn=GUICtrlCreateButton("Source",5,25,50,20)
GUICtrlSetOnEvent($sourcebtn, "source")
$targetbtn=GUICtrlCreateButton("Target",5,65,50,20)
GUICtrlSetOnEvent($targetbtn, "target")
$addbtn=GUICtrlCreateButton("Add",315,65,50,20)
GUICtrlSetOnEvent($addbtn, "addbtn")
$startbtn=GUICtrlCreateButton("START",485,135,60,20)
GUICtrlSetOnEvent($startbtn, "startbtn")
$sourceinput=GUICtrlCreateInput("",60,25,250,20)
$targetinput=GUICtrlCreateInput("",60,65,250,20)
$job=GUICtrlCreateList("",5,160,540,215,$ES_READONLY)
GUICtrlSetState($sourceinput,$GUI_DROPACCEPTED)
GUICtrlSetState($targetinput,$GUI_DROPACCEPTED)
GUICtrlSetState($startbtn,$GUI_HIDE)
GUISetState(@SW_SHOW,$main)
ControlFocus("","",$sourceinput)

dim $accelkeys[1][2]=[["{ENTER}",$addbtn]]
GUISetAccelerators($accelkeys)

Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') ;used in..........
Local $ptr = DllCallbackGetPtr($callback) ;............... _CopyWithProgress
local $size ;size of task (dir or single file)
local $count ;used to help with padding in the listbox
local $fill ;the spacing for above
local $queue ;the list of what is being copied (all tasks)
local $totalfiles ;total number of files to be copied
local $totalsize ;total byte count of files
local $donesofar ;total bytes copied so far
local $bytes ;used as placeholder in __Progress
local $failedfiles ;string of failed copies
local $failed ;count of failures
local $stop, $baselen, $showfilename, $showtotalprog, $totalslide, $fileslide, $target
Global $startcopy = false;<-------------------------------------------------------------------------------
Do
    sleep(1000)

    if $startcopy Then;<-------------------------------------------------- if loop added
        guictrlsetstate($startbtn,$GUI_DISABLE);we don't want th efunction called twice
        starbtnreal()
        $startcopy = False
        guictrlsetstate($startbtn,$GUI_ENABLE)
    EndIf
    
until False

func source()
    GUICtrlSetData($sourceinput,FileSelectFolder("Select a folder",""))
EndFunc

func target()
    GUICtrlSetData($targetinput,FileSelectFolder("Select a folder","",1))
EndFunc

func close()
    Exit
EndFunc

func addbtn()
    $source=GUICtrlRead($sourceinput)
    $target=GUICtrlRead($targetinput)
    if not FileExists($target) then DirCreate($target)
    if FileExists($source) and FileExists($target) Then
    $wait=GUICtrlCreateLabel("Please wait, files are being enumerated",100,100,400,20)
    If StringInStr(FileGetAttrib($source), "D") > 0 Then
    $count+=1
    for $padding=1 to $count
    $fill&=" "
    Next    
    $sourceinfo=DirGetSize($source,1)
    GUICtrlSetData($job,$source&" -> "&$target)
    GUICtrlSetData($job,"("&_StringAddThousandsSep($sourceinfo[1])&" files "&_StringAddThousandsSep(round($sourceinfo[0]/1000000,2))&"MB)")
    GUICtrlSetData($job,$fill)
    $size+=$sourceinfo[0]
    $totalfiles+=$sourceinfo[1]
    $totalsize+=$sourceinfo[0]
    $queue&=$source&chr(1)&$target&chr(1)&"D"&chr(1)
    GUICtrlSetData($sourceinput,"")
    GUICtrlSetData($targetinput,"")
    GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
    GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
    GUICtrlDelete($wait)
    ControlFocus("","",$sourceinput)
    GUICtrlSetState($startbtn,$GUI_SHOW)
    Else
    $count+=1
    for $padding=1 to $count
    $fill&=" "
    Next    
    $sourceinfo=FileGetSize($source)
    GUICtrlSetData($job,$source&" -> "&$target)
    GUICtrlSetData($job,"(1 file "&_StringAddThousandsSep(round($sourceinfo/1000000,2))&"MB)")
    GUICtrlSetData($job,$fill)
    $size+=$sourceinfo
    $totalfiles+=1
    $totalsize+=$sourceinfo
    $queue&=$source&chr(1)&$target&chr(1)&"F"&chr(1)
    GUICtrlSetData($sourceinput,"")
    GUICtrlSetData($targetinput,"")
    GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
    GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
    GUICtrlDelete($wait)
    ControlFocus("","",$sourceinput)
    GUICtrlSetState($startbtn,$GUI_SHOW)
    EndIf
    Else
    msgbox(0,"Error","Please check your source and target paths")   
    EndIf
EndFunc

func startbtn();all it does now is to set a flag. I might have made it too short but you can decide.<------------------
    $startcopy = true;get out of here as fast as you can
EndFunc

func starbtnreal();<------------------------------------------------------------------------------------------------------------------
    $display=TimerInit()
    $howlong=TimerInit()
    GUICtrlDelete($startbtn)
    GUICtrlDelete($instructions)
    ControlDisable("","",$sourcebtn)
    ControlDisable("","",$targetbtn)
    ControlDisable("","",$addbtn)
    ;ControlDisable("","",$startbtn)
    ControlDisable("","",$sourceinput)
    ControlDisable("","",$targetinput)
    ControlDisable("","",$job)
    $fileslide=GUICtrlCreateProgress(5,375,265,20)
    $totalslide=GUICtrlCreateProgress(280,375,265,20)
    $stop=GUICtrlCreateCheckbox("STOP",495,135,60,20)
    $showfilename=GUICtrlCreateLabel("",10,100,530,20,$DT_END_ELLIPSIS)
    GUICtrlCreateLabel("Overall progress - ",10,125,430,20)
    $showtotalprog=GUICtrlCreateLabel("",96,125,230,20)
    $breaksources=StringSplit($queue,chr(1))
    for $doit=1 to ($breaksources[0]-1) step 3
    if $breaksources[$doit+2]="D" then 
    $basedir=$breaksources[$doit]
    $target=$breaksources[$doit+1]
    $baselen = StringLen($basedir)
    theheart($basedir)
    EndIf
    if $breaksources[$doit+2]="F" then 
    $source=$breaksources[$doit]
    $target=$breaksources[$doit+1]
    $name=StringTrimLeft($source,StringInStr($source,"\",0,-1))
    $copied = _CopyWithProgress($source,$target&"\"&$name)
    if $copied=0 then 
    $failed+=1
    $failedfiles&=$source&chr(2)
    $lastbyte=0
    $bytes=0
    EndIf
    EndIf
    Next
    GUICtrlSetData($showfilename,"")
    $totaltimetorun=TimerDiff($howlong)
    $minutes=round($totaltimetorun/60000,2)
    if $failed=0 then msgbox(0,"Finished in "&$minutes&" minutes","Finished with no errors")
    if $failed<>0 then
    $yesorno=msgbox(4,"Finished in "&$minutes&" minutes","Finished with "&$failed&" errors, do you want to see the failed files?")
    if $yesorno=6 then
    $failedwindow=GUICreate("Failed Files",@DesktopWidth,300) ;to display the failed files
    $failedlist=GUICtrlCreateList("",5,5,@DesktopWidth-10,290) ;to display the failed files
    GUISetState(@sw_show,$failedwindow) ;done setting up GUI
    StringTrimRight($failedfiles,1) ;take off the trailing delimeter
    $failedarray=StringSplit($failedfiles,chr(2)) ;break up the list of failed files
    for $show=1 to $failedarray[0]-1
    GUICtrlSetData($failedlist,$failedarray[$show]) ;list the failed files
    Next
#cs handle this in the event handler for $GUI_EVENT_CLOSE, maybe set a flag there that this section can test
    Do
    $msg=GUIGetMsg();no use in OnEvent mode
    if $msg=$GUI_EVENT_CLOSE then exit ;when the failed window is closed, quit the program
    until 1=2
#ce
    EndIf
    EndIf
    ;Exit;??? return, but then set all buttoin states back etc
EndFunc

Func theheart($basedir)

    While GUICtrlRead($stop) == 1 ;look for the pause button
    $quit=msgbox(36,"Paused","Quit Now?")
    if $quit=6 then exit ;yes
    if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box 
    WEnd
    $basesearch = FileFindFirstFile($basedir & "\*.*")
    If $basesearch == -1 Then Return 0 ; specified folder is empty!
    While @error <> 1
    $basefile = FileFindNextFile($basesearch)
    ; skip these
    If $basefile == "." Or $basefile == ".." Or $basefile == "" Then
    ContinueLoop
    EndIf
    ; if it's a dir then call this function again (nesting the function is clever ;)
    $formattedfile = $basedir & "\" & $basefile
    If StringInStr(FileGetAttrib($formattedfile), "D") > 0 Then
    theheart($formattedfile)
    Else
    ; Files we need to deal with
    $dest=StringTrimLeft($formattedfile,$baselen)
    
    While GUICtrlRead($stop) == 1 ;look for the pause button
    $quit=msgbox(36,"Paused","Quit Now?")
    if $quit=6 then exit ;yes
    if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box 
    WEnd
    GUICtrlSetData($showfilename,$formattedfile);&" - "&$BytesTransferred / $FileSize * 100&"%")
    if not FileExists($target&$dest) then 
    $copied = _CopyWithProgress($formattedfile,$target&"\"&$dest)
    if $copied=0 then 
    $failed+=1
    $failedfiles&=$formattedfile&chr(2)
    EndIf
    Else
    $donesofar+=FileGetSize($formattedfile)
    GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
    GUICtrlSetData($totalslide,$donesofar / $size * 100)
    EndIf
    $lastbyte=0
    $bytes=0
    endif
    WEnd
    FileClose($basesearch)
    Return 1

EndFunc ;end theheart


Func _CopyWithProgress($inSource, $inDest)
    
; Function to copy a file showing a realtime progress bar
;
; By Paul Niven (NiVZ)
;
; 05/11/2008
;
; Parameters:
;
; $inSource - Full path to source file
; $inDest - Full path to destination file (structure will be created if it does not exist
;
; Returns 0 if copy is successful and 1 if it fails
;
;
; Updates:
;
; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying
;   - Now uses Kernal32 and DllCallBackRegister to provide faster copying
;   Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3
;   See: http://www.autoit.de/index.php?page=Thread&postID=58875
    
    $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1))

    If Not FileExists($DestDir) Then DirCreate($DestDir)
    
    $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0)

    If $ret[0] <> 0 Then
    ; Success
    Return 1
    Else
    ; Fail
    Return 0
    EndIf
    
EndFunc


Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)

    $lastbyte=$bytes
    $bytes=$BytesTransferred
    $bytediff=$bytes-$lastbyte
    $donesofar+=$bytediff
    GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
    GUICtrlSetData($totalslide,$donesofar / $size * 100)
    GUICtrlSetData($fileslide,$BytesTransferred / $FileSize * 100)

EndFunc
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Thanks for the help, I'll look the changes over in more detail later, but I tested it and the same thing still happens - about 100MB in to a large transfer and all controls die. Any other causes you can think of?

Thanks again

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

Thanks for the help, I'll look the changes over in more detail later, but I tested it and the same thing still happens - about 100MB in to a large transfer and all controls die. Any other causes you can think of?

Thanks again

Ian

I hadn't tried running it so I tried both versions and unfortunately they both work fine for me. I transferred a folder of about 1.3Gb and with a largest file of 150Mb but I didn't see any problem.

I'm using XP SP3, AutoIt 3.3.0.0.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I hadn't tried running it so I tried both versions and unfortunately they both work fine for me. I transferred a folder of about 1.3Gb and with a largest file of 150Mb but I didn't see any problem.

I'm using XP SP3, AutoIt 3.3.0.0.

Yeah, like I put in the title, issues with XP are seldom but I have seen it, Vista and 7 is very problematic though.

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

Yeah, like I put in the title, issues with XP are seldom but I have seen it, Vista and 7 is very problematic though.

Ian

Sorry if I've wasted your time so far.

I can't easily try it in Vista. The next thing I would try is running a separate process for the copying, and use the callback to send a message to the 'parent' process with the data for the progress bars.

Have you tried replacing the progress bars with simple labels showing the percents to see if the problem is connected to the progress bars?

Also, what happens if you don't have a callback. Does the gui behaviour change? (Just to eliminate the callback as a cause of the problem.)

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

This is the same old problem with the CopyWithProgress scripts and large files. martin was right, the script is hung up waiting for the DllCall() to return and the OS thinks the script is non responsive because it is not processing messages. Your only options are (as marting suggested) a separate process that will do the copy and update the progress bars, or a DLL that you can call a multithreaded function to do the copy.

Link to comment
Share on other sites

Thanks guys, a separate process is something I didn't think about, I'll see about that one.

As far as trying without ProgressBars, one silly test was I used Sliders instead, and Vista and 7 can BOTH keep up with the percents, kinda funny, but ProgressBars can't keep up. Having just labels for the progress does the same thing.....

I'll see if I can get a separate process going, but have never done that before so it might take some flailing around to get it right.

@Martin - please, you haven't wasted my time!! ;) I appreciate the help!!

Thanks

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

...

I'll see if I can get a separate process going, but have never done that before so it might take some flailing around to get it right.

If you've never done it before then have a look at ChrisL's interprocess communication udf.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Per your suggestion I put together a quick test based on ChrisL's UDF, it works but is PAINFULLY slow, is that to be expected? On the upside, as you drag around the GUI with a ProgressBar installed it still updates properly which is pretty exciting, but even copying a 12MB file the ProgressBar filled up so slowly, it was odd. Having Script2 display the status as a TrayTip was also very VERY slow which tells me thta may not be a great way to implement a second process for the purpose of updating a ProgressBar. On a 50MB transfer it was so slow I cancelled it, and wouldn't even attempt a 150MB or so file. The kicker is that the file has copied over in normal time, it is just the transfer of the messages that is so slow. If you enable the Mod command in Script1 you will see the difference.

SOOOO, many thanks for getting me this far, any more ideas on speed improvements??

THANKS!

Ian

Script1:

;Script1
#include "MessageHandler.au3"

local $inDest,$inSource
$Local_ReceiverID_Name = "Script1sReceiverID";This is the ID that the other script will use to send data
$Remote_ReceiverID_Name = "Script2sReceiverID";This is the ID of the script we want to send data too

$hwnd = _SetAsReceiver($Local_ReceiverID_Name)
$myFunc = _SetReceiverFunction("_MyFunc2")

While 1
;~     Sleep(1000)
WEnd

Func _MyFunc2($vText)

    
; Function to copy a file showing a realtime progress bar
;
; By Paul Niven (NiVZ)
;
; 05/11/2008
;
; Parameters:
;
; $inSource  -   Full path to source file
; $inDest   -    Full path to destination file (structure will be created if it does not exist
;
; Returns 0 if copy is successful and 1 if it fails
;
;
; Updates:
;
; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying
;           - Now uses Kernal32 and DllCallBackRegister to provide faster copying
;             Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3
;             See: http://www.autoit.de/index.php?page=Thread&postID=58875
      

    If Not IsDeclared("callback") Then Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str')
    If Not IsDeclared("ptr") Then Local $ptr = DllCallbackGetPtr($callback)

$what=$vText
$where=StringSplit($vText,chr(2))
    
    $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $where[1], 'str', $where[2], 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0)

    If $ret[0] <> 0 Then
    ; Success
        Return 1
    Else
    ; Fail
        Return 0
    EndIf
   
EndFunc


Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)
    
    $Str=round($BytesTransferred / $FileSize * 100,0)
;~  if Mod($Str,10)=0 then $iSent = _SendData($Str,$Remote_ReceiverID_Name)     
    $iSent = _SendData($Str,$Remote_ReceiverID_Name)
    
EndFunc

Script2:

;Script2
#include "MessageHandler.au3"
local $vText
$Local_ReceiverID_Name = "Script2sReceiverID";This is the ID that the other script will use to send data
$Remote_ReceiverID_Name = "Script1sReceiverID";This is the ID of the script we want to send data too

$hwnd = _SetAsReceiver($Local_ReceiverID_Name)
$myFunc = _SetReceiverFunction("_MyFunc2")

$main=GUICreate("prog",400,50,100,100)
$prog=GUICtrlCreateProgress(5,5,390,40)
GUISetState(@SW_SHOW,$main)

$Str ="C:\Documents and Settings\tech\Desktop\test.txt"&chr(2)&"z:\test.txt"      ;InputBox(@ScriptName," I am " & @ScriptName & @crlf & "Enter some data to be sent to the other script")
$iSent = _SendData($Str,$Remote_ReceiverID_Name)


While 1
;~     sleep(100)
WEnd


Func _MyFunc2($vText)
    GUICtrlSetData($prog,number($vText))
EndFunc

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

Per your suggestion I put together a quick test based on ChrisL's UDF, it works but is PAINFULLY slow, is that to be expected? On the upside, as you drag around the GUI with a ProgressBar installed it still updates properly which is pretty exciting, but even copying a 12MB file the ProgressBar filled up so slowly, it was odd. Having Script2 display the status as a TrayTip was also very VERY slow which tells me thta may not be a great way to implement a second process for the purpose of updating a ProgressBar. On a 50MB transfer it was so slow I cancelled it, and wouldn't even attempt a 150MB or so file. The kicker is that the file has copied over in normal time, it is just the transfer of the messages that is so slow. If you enable the Mod command in Script1 you will see the difference.

SOOOO, many thanks for getting me this far, any more ideas on speed improvements??

THANKS!

Ian

Script1:

;Script1
#include "MessageHandler.au3"

local $inDest,$inSource
$Local_ReceiverID_Name = "Script1sReceiverID";This is the ID that the other script will use to send data
$Remote_ReceiverID_Name = "Script2sReceiverID";This is the ID of the script we want to send data too

$hwnd = _SetAsReceiver($Local_ReceiverID_Name)
$myFunc = _SetReceiverFunction("_MyFunc2")

While 1
;~ Sleep(1000)
WEnd

Func _MyFunc2($vText)

 
; Function to copy a file showing a realtime progress bar
;
; By Paul Niven (NiVZ)
;
; 05/11/2008
;
; Parameters:
;
; $inSource - Full path to source file
; $inDest - Full path to destination file (structure will be created if it does not exist
;
; Returns 0 if copy is successful and 1 if it fails
;
;
; Updates:
;
; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying
; - Now uses Kernal32 and DllCallBackRegister to provide faster copying
; Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3
; See: http://www.autoit.de/index.php?page=Thread&postID=58875
 

 If Not IsDeclared("callback") Then Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str')
 If Not IsDeclared("ptr") Then Local $ptr = DllCallbackGetPtr($callback)

$what=$vText
$where=StringSplit($vText,chr(2))
 
 $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $where[1], 'str', $where[2], 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0)

 If $ret[0] <> 0 Then
 ; Success
 Return 1
 Else
 ; Fail
 Return 0
 EndIf
 
EndFunc


Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)
 
 $Str=round($BytesTransferred / $FileSize * 100,0)
;~  if Mod($Str,10)=0 then $iSent = _SendData($Str,$Remote_ReceiverID_Name)     
    $iSent = _SendData($Str,$Remote_ReceiverID_Name)
 
EndFunc

Script2:

;Script2
#include "MessageHandler.au3"
local $vText
$Local_ReceiverID_Name = "Script2sReceiverID";This is the ID that the other script will use to send data
$Remote_ReceiverID_Name = "Script1sReceiverID";This is the ID of the script we want to send data too

$hwnd = _SetAsReceiver($Local_ReceiverID_Name)
$myFunc = _SetReceiverFunction("_MyFunc2")

$main=GUICreate("prog",400,50,100,100)
$prog=GUICtrlCreateProgress(5,5,390,40)
GUISetState(@SW_SHOW,$main)

$Str ="C:\Documents and Settings\tech\Desktop\test.txt"&chr(2)&"z:\test.txt" ;InputBox(@ScriptName," I am " & @ScriptName & @crlf & "Enter some data to be sent to the other script")
$iSent = _SendData($Str,$Remote_ReceiverID_Name)


While 1
;~ sleep(100)
WEnd


Func _MyFunc2($vText)
    GUICtrlSetData($prog,number($vText))
EndFunc

No time to play with this now but the problem is (I think) that you have set the receiver function to be to function which does the whole copy thing. When you have a function which receievs a message the handling of that message is only ended when the function ends, so you should make it as short as possible.

So have a small function as the receive function which sets the details of thefiles to copy in a global variable and sets some flag to say start copy. Then detect this flag in your main idle loop and call the copy function. I think that will make a big difference.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I tried a quick change and this seems to work ok on a 150Mb file.

Script1
#include "MessageHandler.au3"

local $inDest,$inSource
$Local_ReceiverID_Name = "Script1sReceiverID";This is the ID that the other script will use to send data
$Remote_ReceiverID_Name = "Script2sReceiverID";This is the ID of the script we want to send data too

$hwnd = _SetAsReceiver($Local_ReceiverID_Name)
$myFunc = _SetReceiverFunction("_MyFunc3")
Global $where, $what,$startcopy = false, $callback, $ptr

;If Not IsDeclared("callback") Then
$callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str')
; If Not IsDeclared("ptr") Then
$ptr = DllCallbackGetPtr($callback)

While 1
 Sleep(100)
 if $startcopy then
 _MyFunc2()
 $startcopy = False
 EndIf
WEnd

Func _MyFunc3($vText)

; Function to copy a file showing a realtime progress bar
;
; By Paul Niven (NiVZ)
;
; 05/11/2008
;
; Parameters:
;
; $inSource - Full path to source file
; $inDest - Full path to destination file (structure will be created if it does not exist
;
; Returns 0 if copy is successful and 1 if it fails
;
;
; Updates:
;
; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying
; - Now uses Kernal32 and DllCallBackRegister to provide faster copying
; Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3
; See: http://www.autoit.de/index.php?page=Thread&postID=58875



$what=$vText
$where=StringSplit($vText,chr(2))
$startcopy = true
EndFunc
func _MyFunc2()
 $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $where[1], 'str', $where[2], 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0)

 If $ret[0] <> 0 Then
 ; Success
 Return 1
 Else
 ; Fail
 Return 0
 EndIf

EndFunc


Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)

 $Str=round($BytesTransferred / $FileSize * 100,0)
;~ if Mod($Str,10)=0 then $iSent = _SendData($Str,$Remote_ReceiverID_Name)
    $iSent = _SendData($Str,$Remote_ReceiverID_Name)

EndFunc

I also changed Script2 although these changes aren't important in this example, but if the processing in _MyFunc2 were more invloved it would slow down the other script while it waited for the function to complete.

;Script2
#include "MessageHandler.au3"
local $vText
$Local_ReceiverID_Name = "Script2sReceiverID";This is the ID that the other script will use to send data
$Remote_ReceiverID_Name = "Script1sReceiverID";This is the ID of the script we want to send data too

$hwnd = _SetAsReceiver($Local_ReceiverID_Name)
$myFunc = _SetReceiverFunction("_MyFunc2")

$main=GUICreate("prog",400,50,100,100)
$prog=GUICtrlCreateProgress(5,5,390,40)
GUISetState(@SW_SHOW,$main)

$Str =InputBox(@ScriptName," I am " & @ScriptName & @crlf & "Enter some data to be sent to the other script")
$iSent = _SendData($Str,$Remote_ReceiverID_Name)
ConsoleWrite("started" & @CRLF)
$vTexta = 0
$vTextb = 0
While 1
sleep(100)
if $vTextA <> $vTextb Then
 GUICtrlSetData($prog,$vTextA)
 $vTextb = $vTextA
 EndIf
WEnd


Func _MyFunc2($vText)
    $vTextA = Number($vText)
EndFunc
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
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...