vindicta

Copy Single files and Directories with progress bar?

16 posts in this topic

#1 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

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

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

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

BeatsPlayer - Music player.

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

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.

Firefox Profile Backup - Backup/restore previously saved profile.

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

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

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

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

Share this post


Link to post
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

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

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

BeatsPlayer - Music player.

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

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.

Firefox Profile Backup - Backup/restore previously saved profile.

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

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

 

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

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

Share this post


Link to post
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.. 

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

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

1 person likes this

Spoiler

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

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

BeatsPlayer - Music player.

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

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.

Firefox Profile Backup - Backup/restore previously saved profile.

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

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

 

Share this post


Link to post
Share on other sites

#10 ·  Posted

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!

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

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

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

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

BeatsPlayer - Music player.

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

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.

Firefox Profile Backup - Backup/restore previously saved profile.

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

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

 

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#14 ·  Posted

I will create another topic for my GUIAccelerators problem. I figured that someone might get into same boat as me and if there is fix posted in this topic, they will never check it.

Share this post


Link to post
Share on other sites

#15 ·  Posted

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

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

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

BeatsPlayer - Music player.

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

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.

Firefox Profile Backup - Backup/restore previously saved profile.

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

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

 

Share this post


Link to post
Share on other sites

#16 ·  Posted

OOOOH that's a great idea, if winactive, exit. that just blew my mind for a second.

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

  • Similar Content

    • Nareshm
      By Nareshm
      Hi All,
      I have excel file like this
      and i want to cut cell/text from excel to other software.

       
      I have to cut the cell of B column one by one and past into other software
      If Winexists("No Data Found")
      then restore cuted cell and goto next/down side cell
      How to do it ?
    • Mag91
      By Mag91
      Hey Community,
      cause im too new in the Auto it world i will try it with the your help. hopefully.
      I woud like to know how i can handle my Problem.
      ----
      I have a Excel Data with 362 random numbers.
      For Example:
      1166642335374 1172899897343
      .....
      this numbers are a part of the filepath ...example
      D:\Projekte\1166_64233_5374
      as u can see its the first number of the Excel data. After the first 4 numbers it shoud make a "_" than another 5 "_"
      This is my first question. How can i handle this to make it Shell execute.
       
      --------
      Second question:
      If i am in the path.
      For Example:
      D:\Projekte\1166_64233_5374
      the code shoud search for specific PDF Files.
      They are named like: 0050569E364B1ED79B900F73E62660EC.pdf
      the first 15 letters are always the same
      0050569E364B1ED
      when he found this data he has to copy it on a Folder on the Desktop.
      (There can also be 2 or 3 pdfs in one Folder with this letters)
      ----
      Please give me some help :-)
       
       
       
       
       
       
    • Mag91
      By Mag91
      Hey Everybody,
      as you know im on a very low autoit-level.
      My question is: How can i read all PDFs from a Folder wich is open and copy them to a Folder on a Desktop.
       
      The Folder wich contains the PDFs is variable Z:\Projektls\"*"*"*EVERYTIME ANOTHER ENDING"*"*"*"*"
      There can be 1 PDF or even 15 PDFs.
      i tried it with _FileListToArray and _FileCopy but i Need some help to understand this language
       
      THANKS!
       
    • tcurran
      By tcurran
      Here's a short UDF that will, at least in most cases, detect whether a window can be copied from or pasted to programmatically--for example, by Send()ing ctl-c, ctl-v. This is often disabled when programs (like your AutoIt script) run at a lower UAC integrity level than the application they are trying to operate on.
      #include <WinAPI.au3> Func _WindowIsPasteable($handle) ;accepts window handle; returns true or false whether a window will accept Ctl-C, Ctl-V Local $bCanPaste = True Local $hTestWindowPID = 0 Local $hTestWindowTID = _WinAPI_GetWindowThreadProcessId($handle, $hTestWindowPID) _WinAPI_AttachThreadInput(_WinAPI_GetCurrentThreadId(), $hTestWindowTID, True);attach to window we want to paste into $bCanPaste = _WinAPI_GetFocus() ;Test whether window is paste-able--returns False if it is not _WinAPI_AttachThreadInput(_WinAPI_GetCurrentThreadId, $hTestWindowTID, False);detach from window thread Return $bCanPaste EndFunc Pass it a window handle; it returns true or false whether a window will accept programmatic pasting. The function may not work on the CMD window, since it handles the clipboard uniquely.
      This function works by attaching to the program thread of the window whose handle it receives, then attempting to perform a GetFocus on that thread. In most cases, the attempt will fail if the window will not accept programmatic copy-paste.
    • KimberlyJillPereira
      By KimberlyJillPereira
      May I know how to copy the first 10 characters in excel and paste it in the file explorer textbox? How to do? I know that you show use the StringLeft() function but I am not sure how to do. Please help me. Thank you!