Jump to content

Copy Single files and Directories with progress bar?


vindicta
 Share

Recommended Posts

Hello Everyone,

Please pardon my noobiness. I am working on backup restore script where a progress bar is required. I have tried using following code which works fine with folders but not really with single file because robocopy :(

Func CopyFolder($srcDir, $destDir, $part)  ;======> $part shows whats being copied (e.g. Desktop, Documents etc.)
    If StringRight($srcDir, 1) = "\" Then $srcDir = StringLeft($srcDir, StringLen($srcDir) - 1)
    If Not FileExists($destDir) Then DirCreate($destDir)
    $srcSize = DirGetSize($srcDir, $DIR_EXTENDED)
    $1_percent = $srcSize[0] / 100
    $cmd = 'C:\Windows\System32\robocopy.exe "' & $srcDir & '" "' & $destDir & '" /E /Z /XO /XX /FFT /XJ /NDL /NJH /FP /ETA /NP /V /R:10 /W:5 /LOG+:"' & $logFile & '" /XF desktop.ini thumbs.db'

    Run(@ComSpec & " /c " & $cmd, "", @SW_HIDE)
    Do
        Sleep(300)
    Until ProcessExists("robocopy.exe")
    ProgressOn($part, $1_percent & "%", "", 0, 0, 16)
    Do
        $destSize = DirGetSize($destDir, $DIR_EXTENDED)
        ProgressSet(Round($destSize[0] / $1_percent, 2), Round($destSize[0] / (1024 * 1024), 2) & " MB of " & Round($srcSize[0] / (1024 * 1024), 2) & " MB copied", Round($destSize[0] / $1_percent, 2) & "%")
        Sleep(200)
    Until ProcessExists("robocopy.exe") = 0
    ProgressOff()
    FileWriteLine($logFile, @CRLF & @CRLF)

EndFunc   ;==>CopyFolder

Part of the problem is that I need to generate logs of files being copied. One particular problem is firefox profile directory. the directory is named as oi3jdslk.default or asdwdx.new and I need to copy places.sqlite from this directory.

Xcopy manages to copy FROM this directory but not TO this directory because of wildcards

Then I came across this neat script 

Func CopyFile($fromFile, $todirectory)
    Local $FOF_RESPOND_YES = 16
    Local $FOF_SIMPLEPROGRESS = 256
    $winShell = ObjCreate("shell.application")
    $winShell.namespace($todirectory).CopyHere($fromFile, $FOF_RESPOND_YES)
EndFunc   ;==>CopyFile

It helped me copy other single files but not the one required from firefox profile folder. Here is how I am trying to process that

$path = @UserProfileDir & "\AppData\Roaming\Mozilla\Firefox\" & $ffDir & "\places.sqlite"
CopyFile($path, $BUFolder & "Mozilla") ;===> $BUFolder = "E:\" & @username & " - Backup\"
              
#cs ======================================================

$ffDir is another variable derived from this function. This variable is the gets the default firefox profile to copy places.sqlite from

$ffDir is returned as Profiles\xbsen2s.default (Firefox randomizes the profile directory for extra security(?). At least that's what they say.

#ce ======================================================

Func FFProfile()
    Local $iniFile = @UserProfileDir & "\AppData\Roaming\Mozilla\Firefox\profiles.ini"
    Local $ddNumber
    Local $ddLine
    Local $Line
    If FileExists($iniFile) Then
        FileOpen($iniFile, 0)
        For $i = 1 To _FileCountLines($iniFile)
            $Line = FileReadLine($iniFile, $i)
            If StringInStr("DEFAULT=1", $Line) Then
                $ddNumber = $i - 1
                ExitLoop
            ElseIf StringInStr("Name=default", $Line) Then
                $ddNumber = $i + 2
            EndIf
        Next
        $ddLine = FileReadLine($iniFile, $ddNumber)

        $ffDir = StringReplace(StringTrimLeft($ddLine, 5), "/", "\")
        $ffInstall = 1
    Else
        $ffInstall = 0
    EndIf
    FileClose($iniFile)
EndFunc   ;==>FFProfile

I really like how natural the progress bar from second copy script look like and would like to keep the progress bar uniform across the program. I am willing to learn if anyone can point me in right direction and help me achieve this.

Any help is highly appreciated!!

Edited by vindicta
Added more information regarding $ffDir
Link to comment
Share on other sites

Im confused about the problem, i read about the progress bar and a dificulty on copying

places.sqlite

Can you clarify a bit the problem? The progress bar is jerky?

Why not read the ini for the profile name and copy?

Edited by careca
Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

Sample Firefox Default Profile Directory - C:\Users\<username>\AppData\Roaming\Mozilla\Firefox\Profiles\vmgdb4fl.default

File to be copied from this directory - places.sqlite

The progress bar is not jerky. The reason it does not work is because robocopy cannot copy single files. xcopy can copy it from above directory to backup directory but cannot copy it back from backup directory to above directory. because the destination directory has a dot in its name. This is what Xcopy says

Does C:\Users\<username>\AppData\Roaming\Mozilla\Firefox\Profiles\vmgdb4fl.default  specify a file name or directory name on the target (F = file, D = directory)?

Now the copy function can copy this file into default profile directory but I am not sure what can I use here

Do
    $destSize = FileGetSize($destDir)
    ProgressSet(Round($destSize / $1_percent, 2), Round($destSize / (1024 * 1024), 2) & " MB of " &         Round($srcSize / (1024 * 1024), 2) & " MB copied", Round($destSize / $1_percent, 2) & "%")
        Sleep(200)
    Until ProcessExists("robocopy.exe") = 0   ;<==== What can be used as determining condition to make sure that file has been successfull copied before progress bar disappears. copy command does not have an image name in tasklist as it is a part of command prompt itself.

I am reading profiles.ini to determine what the default firefox profile is. places.sqlite file contains all the bookmarks, history and download history and my only goal regarding firefox is to make a backup of bookmarks.

Edited by vindicta
To provide more information
Link to comment
Share on other sites

Any special reason why you use xcopy instead of the autoit filecopy?

In any case, i think i would rename the folder, removing the dot, then use xcopy, then rename the folder again to include the dot.

What do you think?

Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

Yashied has created an excellent UDF that will do what you want Here There are two examples, one to copy a file and the other a directory. In the while loop there is some code below

Switch $State[5]
                Case 0
                    GUICtrlSetData($Progress, 100)
                    MsgBox(64, '', 'Folder was successfully copied.', 0, $hForm)
                Case 1235 ; ERROR_REQUEST_ABORTED
                    MsgBox(16, '', 'Folder copying was aborted.', 0, $hForm)
                Case Else
                    MsgBox(16, '', $State[6] & ' was not copied.' & @CR & @CR & $State[5], 0, $hForm)
            EndSwitch

You can put your code to log the file under Case 0. The $State array also provides loads of info on the copy progress, such as amount copied/ remaining etc. Look in the main udf for the _Copy_GetState() function

Link to comment
Share on other sites

1 hour ago, careca said:

Any special reason why you use xcopy instead of the autoit filecopy?

In any case, i think i would rename the folder, removing the dot, then use xcopy, then rename the folder again to include the dot.

What do you think?

Agreed that FileCopy() manages to copy the file to any directory regardless of what the directory name is, period or not. However, I am not sure how to implement ProgressBar with built in FileCopy... 

That being said, I think I managed to fix my own issue.

$cmd = 'ECHO F | xcopy /y /f /d /v "' & $BUFolder & 'Mozilla\places.sqlite" "' & @UserProfileDir &                  '\AppData\Roaming\Mozilla\Firefox\' & $ffDir & '"'
ConsoleWrite($cmd)
    $srcSize = FileGetSize($BUFolder & "Mozilla\places.sqlite")
    $1_percent = $srcSize / 100
    Run(@ComSpec & " /c " & $cmd, "", @SW_HIDE)
    While ProcessExists("xcopy.exe")
        Sleep(300)
    WEnd
    ProgressOn("Firefox", $1_percent & "%", "", 0, 0, 16)
    Do
        $destSize = FileGetSize(@UserProfileDir & "\AppData\Roaming\Mozilla\Firefox\" & $ffDir & "\places.sqlite")
        ProgressSet(Round($destSize / $1_percent, 2), Round($destSize / (1024 * 1024), 2) & " MB of " & Round($srcSize / (1024 * 1024), 2) & " MB copied", Round($destSize / $1_percent, 2) & "%")
        Sleep(200)
    Until ProcessExists("xcopy.exe") = 0
    ProgressOff()

"ECHO F | " passes an F to this question

Does C:\Users\<username>\AppData\Roaming\Mozilla\Firefox\Profiles\vmgdb4fl.default  specify a file name or directory name on the target (F = file, D = directory)?

if and when xcopy gets confused if the file being copied is File or Directory, which in my case is a file.

It worked like a charm in last few test runs but I would still like to improve on my Progress bar as this is not the smoothest of all and seems a bit glitchy.

Edited by vindicta
Link to comment
Share on other sites

22 minutes ago, benners said:

Yashied has created an excellent UDF that will do what you want Here There are two examples, one to copy a file and the other a directory. In the while loop there is some code below

Switch $State[5]
                Case 0
                    GUICtrlSetData($Progress, 100)
                    MsgBox(64, '', 'Folder was successfully copied.', 0, $hForm)
                Case 1235 ; ERROR_REQUEST_ABORTED
                    MsgBox(16, '', 'Folder copying was aborted.', 0, $hForm)
                Case Else
                    MsgBox(16, '', $State[6] & ' was not copied.' & @CR & @CR & $State[5], 0, $hForm)
            EndSwitch

You can put your code to log the file under Case 0. The $State array also provides loads of info on the copy progress, such as amount copied/ remaining etc. Look in the main udf for the _Copy_GetState() function

Thank you for this. However, a critical part of my program is to log files that are being moved around. I am not sure if Yashied's UDF will be able to help me with that.. 

Link to comment
Share on other sites

20 minutes ago, vindicta said:

Thank you for this. However, a critical part of my program is to log files that are being moved around. I am not sure if Yashied's UDF will be able to help me with that.. 

That shouldn't be a problem.

Quote

You can put your code to log the file under Case 0. The $State array also provides loads of info on the copy progress, such as amount copied/ remaining etc. Look in the main udf for the _Copy_GetState() function

One of the properties of the $state array is the current file being copied ($state[6]). Just log that.

Link to comment
Share on other sites

You can store the file list to array, then copy and log at the same time with a progress bar.

Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

3 hours ago, careca said:

You can store the file list to array, then copy and log at the same time with a progress bar.

That's a really good idea, that way I can also show the file being copied instead of just MBs.

I will also try Yashied's UDF and see where that takes me.

Thank you @careca and @benners for all your help. Really appreciate it!

Link to comment
Share on other sites

One more question, if you guys don't mind.

Func CopyFolder($srcDir, $destDir, $part)
    If StringRight($srcDir, 1) = "\" Then $srcDir = StringLeft($srcDir, StringLen($srcDir) - 1)
    If Not FileExists($destDir) Then DirCreate($destDir)
    $list = _FileListToArray($srcDir)
    $srcSize = DirGetSize($srcDir, $DIR_EXTENDED)
    $1_percent = $srcSize[0] / 100
    $cmd = 'C:\Windows\System32\robocopy.exe "' & $srcDir & '" "' & $destDir & '" /E /Z /XO /XX /FFT /XJ /NDL /NJH /FP /ETA /NP /V /R:10 /W:5 /LOG+:"' & $logFile & '" /XF desktop.ini thumbs.db'

    Run(@ComSpec & " /c " & $cmd, "", @SW_HIDE)
    Do
        Sleep(300)
    Until ProcessExists("robocopy.exe")
    ProgressOn($part, $1_percent & "%", "", 0, 0, 16)
    $fileList = _FileListToArray($srcDir)
    For $i = 1 To $fileList[0]
        Do
            $file = $fileList[$i]
            $destSize = DirGetSize($destDir, $DIR_EXTENDED)
            ProgressSet(Round($destSize[0] / $1_percent, 2), "File being copied : " & $file & @CRLF & Round($destSize[0] / (1024 * 1024), 2) & " MB of " & Round($srcSize[0] / (1024 * 1024), 2) & " MB copied", Round($destSize[0] / $1_percent, 2) & "%")
            Sleep(200)
        Until ProcessExists("robocopy.exe") = 0
    Next
    ProgressOff()
EndFunc

This is what my copy function looks like now. I love how the file names are being display. However, I am stumped at one point. Right now it shows file name/directory name but not the files inside subdirectory. I have no idea how to achieve this...

Edited by vindicta
Link to comment
Share on other sites

Instead of _FileListToArray use _FileListToArrayRec (means recursive)

any problems, we're here.

Example:

#include <File.au3>
CopyFolder()
Func CopyFolder()
    ProgressOn('Progress', "%", "", 0, 0, 16)
    $fileList = _FileListToArrayRec('C:\Users\careca\Desktop\mp3', '*', 0, 1, 0, 2)
    For $i = 1 To $fileList[0]
            ;FileCopy($fileList[$i], $fileList[$i])
            ProgressSet(Round($i / $fileList[0]*100, 2), $fileList[$i], Round($i / $fileList[0]*100, 2)&"%")
            Sleep(300)
    Next
    ProgressOff()
EndFunc

In the loop, you can include that log you talked about, and remove the sleep, i only added it to see the progress bar, otherwise would be too fast for the example.

Edited by careca
Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
Share on other sites

Cool, I will try it today and update how it goes. A small off topic question but is regarding the same utility, this function is a part of. I am trying to setup GUI accelerator to close the utility as soon as esc is pressed.  It works fine with hotkey but I want to make sure that the utility only exits if its window was active when esc was pressed. The exit function checks if the button clicked with Backup or Restore.

If pressed backup, $button = 1

if pressed restore, $button = 2

the value of $button is set inside backup() or restore() functions

Opt("GUIOnEventMode", 1)
Opt("GUICoordMode", 1)

$Form1 = GUICreate("Form1", 419, 124, 238, 194, $WS_DLGFRAME)
$B_backup = GUICtrlCreateButton("Backup", 48, 40, 145, 41)
$B_restore = GUICtrlCreateButton("Restore", 224, 40, 145, 41)

;================ > HotKeySet('{ESC}', "terminate")
GUICtrlSetOnEvent($B_backup, "Backup")
GUICtrlSetOnEvent($B_restore, "Restore")
GUISetState(@SW_SHOW)
Dim $accelKey[1][2] = [["{ESC}", terminate()]]
GUISetAccelerators($accelKey)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

 

Close function:

func terminate()
Do
    $msg = GUIGetMsg()
Until $msg <> 0

While 1
        If $button = 1 Then
            ProcessClose("robocopy.exe")
            MsgBox(16, "Abort!", "Backup Aborted!")
            exit
        ElseIf $button = 2 Then
            ProcessClose("robocopy.exe")
            MsgBox(16, "Abort!", "Restore Aborted!")
            exit
        Else
            While 1
                For $i = 3 To 1 Step -1
                    SplashTextOn("Closing Utility...", $i, 130, 54, -1, -1, 0, "Calibri", "", 900)
                    Sleep(1000)
                Next
                ExitLoop
            WEnd
            SplashOff()
            Exit
WEnd

What am I doing wrong here? The utility closes as soon as it launches with Splash text.

 

Edited by vindicta
Link to comment
Share on other sites

While 1
    For $i = 3 To 1 Step -1
    SplashTextOn("Closing Utility...", $i, 130, 54, -1, -1, 0, "Calibri", "", 900)
    Sleep(1000)
    Next
    ExitLoop
WEnd
SplashTextOn("Closing Utility...", $i, 130, 54, -1, -1, 0, "Calibri", "", 900)
Sleep(3000)

I dont know, just seems a lot of lines for a simple job.

As far as the esc close function goes, why not use hotkey, and then check for the window exists or something?

Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

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

×
×
  • Create New...