1 (изменено: Dr.Jekyll, 2013-11-17 19:06:19)

Тема: AHK: FileCopyDir + Progress bar

Добрый день всем!

Возник вопрос, который не удалось решить самому и не смог найти на форумах:

Как прикрутить прогресс бар к копированию директорий ( именно - директорий, а не файлов ), чтобы шкала прогресса всякий раз доходила до конца независимо от размера копируемой директории и прогресс бар выключался по завершении копирования?

Удалось ли это кому-нибудь сделать и как? Если возможно, напишите работающий пример, пожалуйста.

Типа:

FileSelectFolder, CopyFrom, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}, 2, Что будем копировать?
FileSelectFolder, CopyTo, ::{20d04fe0-3aea-1069-a2d8-08002b30309d}, 3, Куда будем копировать?
FileCopyDir, %CopyFrom%, %CopyTo%, 1

Progress, ................

Progress, Off
MsgBox, Копирование %CopyFrom% завершено.
ExitApp
Лучше день потерять, потом за пять минут долететь!

2 (изменено: serzh82saratov, 2013-11-17 22:56:01)

Re: AHK: FileCopyDir + Progress bar

Если интересует вызов стандартного диалога копирования с прогрессом, то:


Source = D:\Programms\=Other ; Что будем копировать 

DestFolder = C:\Users\sergey\Desktop ; Куда будем копировать
 
ComObjCreate("Shell.Application").NameSpace(DestFolder).CopyHere(Source) 
return

Если нужен свой прогресс, то в файловом цикле копировать поштучно файлы, и после каждого копирования проверять например размер папки приёмника, в случае с переписыванием файлов чуть сложнее. В любом случае надо учитывать перед копированием есть-ли одинаковые по имени файлы в приёмнике и источнике. Минус тут - обновление только после копирования каждого файла. Обойти это можно запустив отдельным потоком (можно и не AutoHotkey) копирование папки, и уже с нужным интервалом делать проверку размера папки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

3 (изменено: Dr.Jekyll, 2013-11-17 23:56:06)

Re: AHK: FileCopyDir + Progress bar

Большое благодарю за ответ, serzh82saratov ! Я только недавно начал изучать AHK, потому не очень разбираюсь в нюансах. Конечно, хотелось бы сделать свой прогресс, со своим интерфейсом. Я предполагал, что здесь надо задействовать "FileGetSize" или "A_LoopFileSize", если я не ошибаюсь. Вероятно, такой подход к вопросу весьма затормозит сам процесс копирования? Но дело не в том. Меня уже заинтересовало, как это реализовать (принципа ради, но не кОрысти для!   ). Если можно, напишите рабочий скрипт с Gui - мне легче будет разобраться в вопросе на наглядном примере .....

Лучше день потерять, потом за пять минут долететь!

4

Re: AHK: FileCopyDir + Progress bar

Пока такой пример с запуском 2 процесса. Пример простой, сработает только при копировании в пустую или несуществующую папку:


SetBatchLines -1  
 
Source = D:\Programms\=Other 
DestFolder = C:\Users\sergey\Desktop\=Other
   
AHKcode =
(
#NoTrayIcon    
FileDelete, `%A_ScriptFullPath`%
FileCopyDir, %Source%, %DestFolder%, 1
    MsgBox FileCopyDir ExitApp
ExitApp
) 
 
FileAppend, %AHKcode%, %A_ScriptDir%\FileCopyDir.ahk
Run %A_ScriptDir%\FileCopyDir.ahk

SourceSize := FolderSize(Source)
Gui, Add, Progress, h20 w200 vProgress Border Range0-%SourceSize% 
Gui, Show
 
Loop   {
    DestSize := FolderSize(DestFolder) 
    GuiControl,, Progress, %DestSize%
    If DestSize >= SourceSize
        ExitApp
    Sleep 100
} 
 
FolderSize(Folder, FolderSize := 0)  {
    Loop, %Folder%\*.*, , 1
        FolderSize += %A_LoopFileSizeKB%  
    return FolderSize
}

Представив дальнейшую отладку для отмены копирования, связи между двумя скриптами и.т.п. хочется отказатся от этой идеи. Есть мысль создать вместо Progress, контрол ActiveX HTMLFile, и в коде JScript прописать проверку папки, я так понял он выполняется "своим"  потоком (на примере с бегущей строкой) но тут я не могу помочь. Но опять же проверка целевой папки на размер не лучший способ, т.к. паралельно может производится другое изменение файлов в папках.
Так что наверное всё-таки проще и точнее обновлять Progress после копирования каждого файла. Но если в папке например один большой файл, то толку от этого тоже нет.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

5 (изменено: Dr.Jekyll, 2013-11-19 17:06:05)

Re: AHK: FileCopyDir + Progress bar

Большущее спасибо за пример! Все отлично работает. Только заметил, что на копировании больших файлов происходит резкий скачек прогресса, а затем прогресс "замерзает". ... В принципе, я не планирую копирование больших файлов этим скриптом, но, все же ... Может есть другие несложные схемы, чтобы избежать этого?

Благодарю за помощь!

Лучше день потерять, потом за пять минут долететь!

6

Re: AHK: FileCopyDir + Progress bar

Только заметил, что на копировании больших файлов происходит резкий скачек прогресса

Тут не знаю чем помочь, я почему-то думал, что размер целевой папки должен постепенно увеличиваться в процессе копирования большого файла, но это оказалось не так.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

7

Re: AHK: FileCopyDir + Progress bar

Хотя есть вариант взять все файлы в папке, если прогресс нужен с диапазоном 1000, то читать в буфер равный 1000-й части общего объёма и записать в целевой, обновить прогресс.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

8 (изменено: Dr.Jekyll, 2013-11-19 18:53:22)

Re: AHK: FileCopyDir + Progress bar

Пока все это сложно для меня ... в процессе изучения

Кстати, довольно интересная функция ComObjCreate ! Я не знал об этом. Пользовался только русским справочником, а там этого нет. Сейчас посмотрел в родном, английском там есть - это более полный справочник, надо на него переходить ...

Source = D:\Programms\=Other ; Что будем копировать 

DestFolder = C:\Users\sergey\Desktop ; Куда будем копировать
 
ComObjCreate("Shell.Application").NameSpace(DestFolder).CopyHere(Source) 
return

А как можно сделать, чтобы в директорию назначения "DestDir" (DestFolder) копировалось только содержимое "SourceDir" (Source), а не вся директория с исходным именем?

Лучше день потерять, потом за пять минут долететь!

9

Re: AHK: FileCopyDir + Progress bar

Вот параметры: CopyHere
Я так понял что нужно 4096, но что-то идёт не так:

ComObjCreate("Shell.Application").NameSpace(DestFolder).CopyHere(Source, 4096) 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

10 (изменено: Dr.Jekyll, 2013-11-20 06:44:43)

Re: AHK: FileCopyDir + Progress bar

4096 = тот же результат.

CopyHere - "... Вызов метода приводит к тому же эффекту, что и перетаскивание файлов в проводнике."


ComObjCreate("Shell.Application").NameSpace(DestFolder).CopyHere(Source)

- полное копирование всей директории с вложенными файлами и папками. ... Надо подумать, как копировать содержимое директории ...

Лучше день потерять, потом за пять минут долететь!

11

Re: AHK: FileCopyDir + Progress bar

ComObjCreate("Shell.Application").NameSpace(DestDir).CopyHere(SourceDir "\*")

Вот так копируется только содержимое SourceDir, но тогда прогресс появляется только на копировании директории большого объема ....

Конечно, больше интересует сделать свой прогресс ...

Лучше день потерять, потом за пять минут долететь!

12 (изменено: serzh82saratov, 2015-09-20 19:01:02)

Re: AHK: FileCopyDir + Progress bar

Так я вижу решение:


#SingleInstance Force
#Persistent   
#MaxMem 4095
SetBatchLines -1 

Source =  
Dest =  
ProgressStep := 1000
 
Gui, Add, Text, y+10 vText -Wrap r2 w555
Gui, Add, Progress, vProgress wp Range1-%ProgressStep%
Gui, Show 

FileCopyDir( Source, Dest, 1, 1) 
Return

 ; rewrite - Переписывать файлы
 ; recurse - Рекурсия в папки, т.е. всё содержимое. Иначе только файлы из корня.
 
FileCopyDir( Source, Dest, rewrite := 0, recurse := 0)  { 
    Global ProgressStep
    
    FileCreateDir, %Dest%
    DelSource := StrLen(Source) + 1, AllSize := 0
    
    Loop, %Source%\*.*, , %recurse%
    {
        If (!rewrite)
        { 
            RASHNDOCT := FileExist( Dest . SubStr( A_LoopFileLongPath, DelSource))
            
            If (RASHNDOCT != "" && !InStr( RASHNDOCT, "D"))
                Continue 
        }
        
        list .= A_LoopFileLongPath "`n"
        AllSize += A_LoopFileSize
    }

    list := SubStr(list, 1, -1)
    ByteStep := Ceil(AllSize / ProgressStep), IndexByteStep := 0          
    
    Loop, parse, list, `n
    {
        GuiControl, , Text, % "Сейчас копируется:`n" A_LoopField 
        DestFileName := Dest . SubStr(A_LoopField, DelSource)  
        
        If recurse
        {
            IsDestDir := SubStr(DestFileName, 1, InStr(DestFileName, "\", , -1))
            RASHNDOCT := FileExist(IsDestDir)
            
            If (RASHNDOCT = "" || !InStr( RASHNDOCT, "D"))
                FileCreateDir, %IsDestDir%
        }
        
        DestFile := FileOpen(DestFileName, "w")
        
        If rewrite
            DestFile.Length := 0
         
        File := FileOpen(A_LoopField, "r") 
        FileSize := File.Length 
        Seek := 0
        
        Loop
        {  
            If restBytes
            {
                End := bufSize := restBytes, restBytes := 0
                
                If (End > FileSize)
                    restBytes := End - FileSize, bufSize := FileSize
            }
            Else
            {
                bufSize := ByteStep, End := Seek + ByteStep
            
                If (End > FileSize)
                    restBytes := End - FileSize, bufSize := ByteStep - restBytes, Seek := FileSize - bufSize
            }
            
            File.Pos := Seek, DestFile.Pos := Seek  
            VarSetCapacity(buf, bufSize, 0) 
            File.RawRead(&buf, bufSize)
            DestFile.RawWrite(&buf, bufSize)  

            If restBytes
                Break
         
            GuiControl, , Progress, % ++IndexByteStep 
            Seek := End  
        }    
    } 
    GuiControl, , Text, Готово
    GuiControl, , Progress, % ProgressStep
    DestFile := "", File := "", VarSetCapacity(buf, 0) 
}
 
GuiClose:
GuiEscape:
    ExitApp 

Можете ещё прикрутить примерное оставшееся время и размер, а также скорость копирования. Возможно также отмену копирования на каждом (в данном примере - тысячном) этапе.
По скорости примерно на 3 - 5 % быстрее чем метод windows.

---

ап:
Поправил для учёта в прогрессе файлов которые не надо переписывать.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

13

Re: AHK: FileCopyDir + Progress bar

serzh82saratov, большущее благодарю за проделанную работу! Все прекрасно работает! Много забугорных форумов перекопал, но ничего не нашел, чтобы хорошо работало!

Русские программеры - The BEST!    Спасибо!

Лучше день потерять, потом за пять минут долететь!