CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Здесь обсуждается всё, что касается макросов.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

Скрипт делался в целях изучения ffi, но оказался довольно шустрым. Также, возможно, кому-то покажется полезным в качестве примера использования ffi, т.к. там (а) используется CallBack-процедура, (б) используются арифметические операции с типом cdata и (в) столкнулся с проблемой: параметры CallBack-функции должен быть типа LARGE_INTEGER, который является union-ом; но в этом случае возникает ошибка при приведении CallBack-процедуры к описанному СИ-типу (ffi.cast).
Теперь задача оформлена в виде модуля; кроме собственно процедуры копирования в модуле есть пример создания классов и готовые классы для отрисовки прогрессбара и вывода сообщения при помощи far.Text (использование объекта этого класса вместо far.Message ускорило копирование в несколько раз(!)) -. Возможно, кому-то покажутся удобными те утилиты, которые этот модуль предоставляет.


По-прежнему остались мелкая"непонятка": у функции CopyFileEx можно указать флаг COPY_FILE_RESTARTABLE (Ход выполнения копирования отслеживается в целевом файле в случае сбоя копирования. Сбойную копию можно перезапустить позже, указав те же значения для lpExistingFileName и lpNewFileName, которые использовались в сбойном вызове). А CallBack-процедура может вернуть значение PROGRESS_STOP (Остановить операцию копирования. Она может быть перезапущена в более позднее время). Но почему-то несмотря на указание этих параметров при прерывании копирования скопированная часть файла стирается. Если кто-то знает, как сделать "дописываемый" файл при поможи процедуры CopyFileEx - поделитесь, пожалуйста, секретом
Кроме этого в скрипте имеется процедура индикатора процесса (как проценты, так и бесконечный). Тоже может кому пригодится...
CopyFileEx_Lua.lua.7z
Модуль BaxUtils.lua с примером использования CopyFileEx_Lua
(7.66 KiB) Downloaded 94 times
Last edited by buniak_a_h on Fri 25 May, 2018 13:31, edited 4 times in total.
2useven10
Posts: 5192
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 309 times

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by 2useven10 »

buniak_a_h wrote: Sun 13 May, 2018 07:24 ffi.cast("LPBOOL", bCancel)
Это некорректно, не падает видимо просто из-за того, что в вашем случае приведётся к NULL.
Надо как-то так: local pbCancel = ffi.new("BOOL[1]"); pbCancel[0] = 0 и соответственно при вызове вместо ffi.cast - pbCancel.
Может это и с прерыванием-возобновлением копирования поможет...
Last edited by 2useven10 on Sun 13 May, 2018 09:45, edited 1 time in total.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

2useven10 wrote: Sun 13 May, 2018 09:28
buniak_a_h wrote: Sun 13 May, 2018 07:24 ffi.cast("LPBOOL", bCancel)
Надо как-то так: local pbCancel = ffi.new("BOOL[1]"); pbCancel[0] = 0
Спасибо. Я чувствовал, что раз указатель, то должно где-то образовываться место.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

2useven10 wrote: Sun 13 May, 2018 09:28 Может это и с прерыванием-возобновлением копирования поможет...
Увы...
А можно ещё вопрос с разыменовыванием?
pbCancel[0] равен 0 независимо от того, прерывал я копирование или нет. Как узнать-то?
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by John Doe »

buniak_a_h wrote: Sun 13 May, 2018 12:28 pbCancel[0] равен 0 независимо от того, прерывал я копирование или нет. Как узнать-то?

Code: Select all

_In_opt_ LPBOOL             pbCancel,
Это же входящее значение
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

John Doe wrote: Sun 13 May, 2018 12:51 Это же входящее значение
Входящее значение - указатель на BOOL-переменную. В MSDN написано что-то странное...
If this flag is set to TRUE during the copy operation, the operation is canceled (Если этот флаг устанавливается в TRUE во время операции копирования, операция отменяется - я правильно перевёл?)
А кто должен писать в неё признак прерывания? Если вызывающая программа, то копирования просто не будет. Если CallBack-процедура, то у неё есть другие, более гибкие способы прерывания... Параллельная ветка или что-нить типа таймера? Тоже странно: вроде как для этого в CallBack=процедуру передаётся lpData, а она уже может прервать копирование...
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by John Doe »

buniak_a_h wrote: Sun 13 May, 2018 13:15 Если CallBack-процедура, то у неё есть другие, более гибкие способы прерывания... Параллельная ветка или что-нить типа таймера? Тоже странно: вроде как для этого в CallBack=процедуру передаётся lpData, а она уже может прервать копирование...
Процедуры может и не быть, она ведь опциональна.
А в вашем случае видимо надо передавать nil.
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by John Doe »

buniak_a_h wrote: Sun 13 May, 2018 07:24 На локальных - тормоз
Сколько раз в секунду прогрессбар выводится?

Code: Select all

elseif os.difftime(os.time(), iTime) < -1 then -- Выключено
Для чего это?
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

John Doe wrote: Sun 13 May, 2018 16:56
buniak_a_h wrote: Sun 13 May, 2018 07:24 На локальных - тормоз
Сколько раз в секунду прогрессбар выводится?
1. Я сейчас переделал: длина прогрессбара = round(Far.Width / 2). Поэтому чем шире окно ФАРа, тем меньше "вес" каждой ячейки, тем чаще выводится. Пересчитывается при каждом вызове CallBack-функции.
2. Скоростные параметры получились такие:файл 3 Гб копируется 45 секунд. Этот же скрипт без вызова CallBack-рутины копирует 25 секунд ("чистая CopyFileEx"). ФАРовская процедура копирует 6 секунд. Плагин FileCopyEx3 копирует порядка 40 секунд и после блокирует результирующий файл.
John Doe wrote: Sun 13 May, 2018 16:56 КОД: ВЫДЕЛИТЬ ВСЁ

elseif os.difftime(os.time(), iTime) < -1 then -- Выключено
Для чего это?
Сначала (пока не дочитал, как работать с cdata-данными) сделал "бесконечный" индикатор (сначала правам концом, потом уменьшается левым - и так до бесконечности). Выяснилось, что мельтешит очень. Эта строка была попыткой выводить индикатор (и вообще выполнять CallBack-процедуру) не чаще, чем раз в секунду. Правда, оказалось тоже некрасиво: на указанном мной файле даже один раз не вырастал до конца. Как будто аварийно закончилось. Как работать со временем точнее, чем с интервалами в 1 секунду - не нашёл: os.time() и (os.difftime() соответственно) выдают целое количество секунд. Точнее, сейчас нашёл (win.GetSystemTimeAsFileTime()) но уже нужда отпала.
Last edited by buniak_a_h on Sun 13 May, 2018 19:19, edited 1 time in total.
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by John Doe »

buniak_a_h wrote: Sun 13 May, 2018 19:18 os.time() и (os.difftime() соответственно) выдают целое количество секунд.
os.clock, а ещё точнее far.FarClock
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by John Doe »

buniak_a_h wrote: Sun 13 May, 2018 19:18 Скоростные параметры получились такие:файл 3 Гб копируется 45 секунд. Этот же скрипт без вызова CallBack-рутины копирует 25 секунд ("чистая CopyFileEx"). ФАРовская процедура копирует 6 секунд.
Попробовал
а) без callback
б) с пустым callback (без вывода прогресса и без ожидания Esc)
в) копирование фаром

Принципиальной разницы во времени не нашёл.

Влияния COPY_FILE_RESTARTABLE тоже не заметил.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

John Doe wrote: Sun 13 May, 2018 21:44 Принципиальной разницы во времени не нашёл.
Ну, цифры же я не придумал!
Я не знаю, от чего зависит. Может, кэш диска. Или параметры системы. У меня - Windows-10 x64.
Кстати, попробовал из cmd дать команду copy /b In\Large.iso Out\ /y. Время на том же файле колеблется от 8 до 25 секунд (без перезагрузки). Но не уменьшается (что было бы естественно при большом кэше), а и растёт и уменьшается. Но в любом случае дольше, чем ФАР копирует!
Last edited by buniak_a_h on Sun 13 May, 2018 22:43, edited 1 time in total.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

John Doe wrote: Sun 13 May, 2018 21:26
buniak_a_h wrote: Sun 13 May, 2018 19:18 os.time() и (os.difftime() соответственно) выдают целое количество секунд.
os.clock, а ещё точнее far.FarClock
В документации ничего непонятно!
os.clock ()
Возвращает примерное количество времени в секундах, потраченное CPU на выполнение программы
far.FarClock
result = far.FarClock ()
Returns:
result: number
os.clock(), вроде, не подходит (при чём тут время CPU, да ещё потраченное на программу)
Про far.FarClock ВООБЩЕ НИЧЕГО НЕ НАПИСАНО! Что за "number"??? Количество секунд с полуночи? Количество миллисекунд? Количество суток с 01.09.1896 01.09.1899
Last edited by buniak_a_h on Sun 13 May, 2018 23:43, edited 1 time in total.
User avatar
buniak_a_h
Posts: 4234
Joined: Sat 20 Apr, 2013 00:17
Location: Санкт-Петробад
Has thanked: 222 times
Been thanked: 642 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by buniak_a_h »

John Doe wrote: Sun 13 May, 2018 21:44 Принципиальной разницы во времени не нашёл.
Кстати, такая странность: У меня есть индикатор загрузки дисков. Так вот: после копирования ФАРом он ещё с пол-минуты показывает загрузку 100%... :-)
Здорово!
Last edited by buniak_a_h on Mon 14 May, 2018 01:17, edited 1 time in total.
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

CopyFileEx_Lua - копирование функцией CopyFileEx с визуализацией и возможностью снятия

Post by John Doe »

buniak_a_h wrote: Sun 13 May, 2018 23:01 В документации ничего непонятно!
http://lua-users.org/wiki/DateAndTime
https://api.farmanager.com/ru/fsf/farclock.html
Post Reply

Return to “Обсуждение макросов”