Что нового

Копирование папки, отображение процесса загрузки буфера и подсчет времени потраченного на процесс (секундомер)

Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
для скриншота окна прогресса и вставки в окно скрипта
Спасибо. Но не могу разобраться. У меня своя функция создания скрина окна без привязки к координатам. Возможно ваш вариант и лучше, но все равно не понятно, как прикрутить любую другую дополнительную функцию.
Вот мой вариант. Можете на нем пояснить?
Код:
#pragma compile(AutoItExecuteAllowed, true)
#RequireAdmin
#include <GUIConstantsEx.au3>
#include <Date.au3>
#include <WindowsConstants.au3>
#include <Timers.au3>
#include <StaticConstants.au3>
#include <WinAPIProc.au3>
#Include <ScreenCapture.au3>
#include <WinAPI.au3>
#include <Clipboard.au3>
#include <GDIPlus.au3>
;#include <поймать окно альт.au3>


Global $timer, $Secs, $Mins, $Hour, $Time, $sTime, $TimeInf, $sPS, $sPD
Global $iPid, $iTM
$hGui = GUICreate('Секундомер', 700, 680, -1, -1, -1, $WS_EX_TOPMOST)
$TimeInf = GUICtrlCreateLabel('00:00:00:000', 8, 8, 330, 81, $SS_CENTERIMAGE + $SS_CENTER, $WS_EX_STATICEDGE)
GUICtrlSetFont(-1, 36, -1, -1, 'Impact')
Local $btStart = GUICtrlCreateButton('Старт', 392, 8, 75, 25)
Local $btStop = GUICtrlCreateButton('Стоп', 392, 48, 75, 25)
Local $sPathSS = GUICtrlCreateInput('', 8, 96, 325, 21)
Local $sPathDD = GUICtrlCreateInput('', 8, 128, 325, 21)
Local $sPathS = GUICtrlCreateButton('Откуда', 392, 96, 75, 25)
Local $sPathD = GUICtrlCreateButton('Куда', 392, 128, 75, 25)
$Temper = GUICtrlCreateLabel('Температура', 480, 8, 150, 50, $SS_CENTERIMAGE + $SS_CENTER, $WS_EX_STATICEDGE)
$Smart = GUICtrlCreateLabel('Модель' & @LF & 'Серийный' & @CR & 'Буква', 480, 58, 150, 150, $SS_LEFT, $WS_EX_STATICEDGE)

$Pic = GUICtrlCreatePic(@ScriptDir & "\screen1.bmp", 8, 170, 330, 200,$WS_SIZEBOX + $WS_SYSMENU)
$LabelPic1 = GUICtrlCreateLabel('Результат1', 8, 370, 330, 25, $SS_CENTERIMAGE + $SS_CENTER, $WS_EX_STATICEDGE)

$Pic2 = GUICtrlCreatePic(@ScriptDir & "\screen2.bmp", 338, 170, 330, 200, $WS_SIZEBOX + $WS_SYSMENU)
$LabelPic2 = GUICtrlCreateLabel('Результат2', 338, 370, 330, 25, $SS_CENTERIMAGE + $SS_CENTER, $WS_EX_STATICEDGE)

$Pic3 = GUICtrlCreatePic(@ScriptDir & "\screen3.bmp", 8, 400, 330, 200, $WS_SIZEBOX + $WS_SYSMENU)
$LabelPic3 = GUICtrlCreateLabel('Результат3', 8, 600, 330, 25, $SS_CENTERIMAGE + $SS_CENTER, $WS_EX_STATICEDGE)

$Pic4 = GUICtrlCreatePic(@ScriptDir & "\screen4.bmp", 338, 400, 330, 200, $WS_SIZEBOX + $WS_SYSMENU)
$LabelPic4 = GUICtrlCreateLabel('Результат4', 338, 600, 330, 25, $SS_CENTERIMAGE + $SS_CENTER, $WS_EX_STATICEDGE)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            FileDelete('copy.txt')
            _Timer_KillTimer($hGui, $iTM)
            ProcessClose($iPid)
            Exit
        Case $sPathS
            GUICtrlSetData($sPathSS, '')
            $sPS = FileSelectFolder('Выбор копируемой папки', '', 0, '', $hGui)
            If Not @error Then GUICtrlSetData($sPathSS, $sPS)
        Case $sPathD
            GUICtrlSetData($sPathDD, '')
            $sPD = FileSelectFolder('Выбор папки назначения', '', 0, '', $hGui)
            If Not @error Then GUICtrlSetData($sPathDD, $sPD)


Case $btStart
            FileDelete('copy.txt')
            If Not ProcessExists($iPid) Then
                If FileExists($sPS) And FileExists($sPD) Then
                    GUICtrlSetData($TimeInf, '00:00:00:000')
                    FileWrite('copy.txt', "$Shell = ObjCreate('Shell.Application')" & @CRLF & "$Shell.NameSpace('" & $sPD & "').CopyHere('" & $sPS & "', 16)")

                    $timer = TimerInit()
                    $iTM = _Timer_SetTimer($hGui, 50, '_TIMER')
                    $iPid = Run(@AutoItExe & ' /AutoIt3ExecuteScript copy.txt')

                    If ProcessExists($iPid) Then

                        While 1
                            Local $ahWin = _WinAPI_EnumProcessWindows($iPid)
                            If Not @error Then

                                If Not StringInStr($ahWin[1][1], 'Autoit') Then
                                    Local $aPosP = WinGetPos($hGui)
                                    WinSetOnTop($ahWin[1][0], '', 1)
                                    WinMove($ahWin[1][0], '', $aPosP[0], $aPosP[1] + $aPosP[3] - 30)
                                    WinSetOnTop($hGui, '', -10)

                                EndIf

                                ExitLoop
                            EndIf
                         WEnd

                    EndIf

                    FileDelete('copy.txt')

                EndIf

            EndIf


        Case $btStop
            FileDelete('copy.txt')
            _Timer_KillTimer($hGui, $iTM)
            ProcessClose($iPid)
            GUICtrlSetData($TimeInf, '00:00:00:000')
            GUICtrlSetData($sPathSS, '')
            GUICtrlSetData($sPathDD, '')
            $iPid = 0
         EndSwitch

WEnd

Func _TIMER($hWnd, $iMsg, $iIDTimer, $iTime)

    If Not ProcessExists($iPid) Then
        FileDelete('copy.txt')
        _Timer_KillTimer($hGui, $iTM)
        $iPid = 0
    EndIf
    _TicksToTime(Int(TimerDiff($timer)), $Hour, $Mins, $Secs)
    $Time = StringFormat('%02i:%02i:%02i:%03i', $Hour, $Mins, $Secs, StringRight(Int(TimerDiff($timer)), 3))
    GUICtrlSetData($TimeInf, $Time)
EndFunc   ;==>_TIMER

Func _SCREEN()


If Not WinExists("[class:OperationStatusWindow]") Then
    MsgBox(4096, 'Сообщение', 'Окно не найдено, завершаем работу скрипта')
    Exit
 Else
    $hWnd = WinGetHandle("[CLASS:OperationStatusWindow]")

;Dim $screen =
Send("!{PRINTSCREEN}")

_ClipBoard_Open(0)
$hBitmap = _ClipBoard_GetDataEx($CF_BITMAP)
_ClipBoard_Close()
_GDIPlus_Startup()
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
_GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\screen.bmp")
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_Shutdown()
Dim $sFile = @ScriptDir & "\screen.bmp"

;_ScreenCapture_SaveImage($sFile, $hBitmap)
ShellExecute($sFile)


 EndIf
EndFunc   ;==>_SCREEN
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
В моем варианте скринится только окно прогресса при определенных процентах. Мой пример не работает?
Если хочешь вставить свою функцию, то в моем примере функцию снимка окна замени на свою
 
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
В моем варианте скринится только окно прогресса при определенных процентах.
Так у меня тоже самое скриниться. Строго окно прогресса в самом конце копирования
Мой пример не работает?
Работает.
Только мне нужно будет потом ещё 3 скрина сделать. Суммарно 4. Сперва копирование из одной папки, потом из другой, третей, четвертой. Под каждый скрин уже нарисована область в окошке секундомера. Сейчас доделываю подписи под каждым скрином (Буква диска, куда копировалась папка и откуда). Правда пока получается только под первым скрином вывести.
Да и просто хочется разобраться
Если хочешь вставить свою функцию, то в моем примере функцию снимка окна замени на свою
Так вот я и не пойму, как её вставить. Хоть функцию "Прювет, мир". Пробовал вызывать окошко с сообщением, типа найдено-не найдено окно копирования. Так либо зацикливается на выводе этого сообщения, либо после его вывода закрывается. Либо ничего не работает. Тоже самое и со скрином.
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Твоя функция скрина непонятна. Зачем хэндл окна если он не используется?
зачем использовать буфер обмена? ведь можно сохранить на диск. почему бы не скринить сразу окно, как в моем примере?. Там не используются координаты, только хэндл окна.
в функция таймера нельзя вставлять циклические функции типа вызова сообщения. будет зависание. в таких функция можно делать подсчет, отслеживание и передачу данных в общий код. то есть, любое действие, которое не требует бесконечного цикла.
 
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
Зачем хэндл окна если он не используется?
Как это не используется? Сразу после него жмутся клавиши для скрина окошка. Как и на реальной системе. ALT+PrntScrn.
И не нужны координаты.
зачем использовать буфер обмена? ведь можно сохранить на диск.
Так из буфера сохраняет на диск, туда, где лежит скрипт. Путь можно указать любой, Можно и как в твоем примере в папку Temp. Потом оттуда для проверки запускается просмотр. Но это только проверка. Она необязательна.
в функция таймера нельзя вставлять циклические функции типа вызова сообщения
Значит я не понял, как запускается скрин. Хотя пробовал не только там вызывать. Именно потому и прошу пояснить на пальцах с коментами в коде, что написано и зачем.
почему бы не скринить сразу окно, как в моем примере?. Там не используются координаты, только хэндл окна.
А можно отдельным кодом функцию скрина? Может так быстрее разберусь что куда?
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Я не вижу в твоей функции использования хэндла, только ожидание класса окна. Еще раз, в моем варианте нет координат. А функция скрина это одна строчка
 
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
Я не вижу в твоей функции использования хэндла, только ожидание класса окна.
Возможно это сказывается то, что autoit занимаюсь около недели и не совсем понимаю, что делаю и говорю. Думал, что вот эта строка
Код:
$hWnd = WinGetHandle("[CLASS:OperationStatusWindow]")

Это и есть получение хендла, или другими словами поймать в фокус окошко процесса копирования. Получил в фокус и нажал клавишу скрина. Потом из буфера сохранил на диск и проверил.
Еще раз, в моем варианте нет координат. А функция скрина это одна строчка
К сожалению, так и не понял, что это за строчка. Верю, что нет координат. Про свою говорил только стой точки зрения, что в моей тоже нет. Просто не понимаю, как она у тебя выглядит. Вообще, весь код, что написан тобой вызывает уважение.
Возможно мне нужно отвлечься на вечер от этого ))) Мозги кипят ))) Но время поджимает
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Код:
_ScreenCapture_CaptureWnd($sPathSC, $hTitleProc, 0, 0, -1, -1, False)

первая переменная это файл сохранения снимка. вторая это хэндл окна прогресса копирования, потом указано, что окно скринить полностью. но если настроить параметры, то можно снимать часть окна
по сути, сама функция скрина окна может быть короче
Код:
_ScreenCapture_CaptureWnd($sPathSC, $hTitleProc)


получение хендла не дает фокус на окне. его нужно активировать
Код:
$hWnd = [URL='https://autoit-script.ru/docs/functions/wingethandle.htm']WinGetHandle[/URL]("[CLASS:OperationStatusWindow]")
WinActivate($hWnd)

рекомендую всегда декларировать переменные и указывать явно область применения
Код:
Global
;или
Local

вместо Dim
 
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
_ScreenCapture_CaptureWnd($sPathSC, $hTitleProc, 0, 0, -1, -1, False)
Странно. У меня снимало окно без графика. Даже тему создавал и никто не подсказал в чем проблема.
получение хендла не дает фокус на окне. его нужно активировать
Теперь больше понятно.
первая переменная это файл сохранения снимка. вторая это хэндл окна прогресса копирования, потом указано, что окно скринить полностью. но если настроить параметры, то можно снимать часть окна
по сути, сама функция скрина окна может быть короче
По сути некоторое количество строк в моей функции тоже получают дескриптор окна, путь куда сохранять.
А вот эту строчку пояснить можете? Концовку
Код:
Local $iProcC = Number(StringRegExpReplace(WinGetTitle($hTitleProc), '[^\d]', '\1'))

Ну и вообще весь процесс прерывания функции. Так понимаю _ProcessSuspend?
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Suspend с параметром 1 это заморозка процесса, чтобы сделать скрин окна, потом идет разморозка и процесс завершает копирование
Сообщение автоматически объединено:

Local $iProcC = Number(StringRegExpReplace(WinGetTitle($hTitleProc), '[^\d]', '\1'))
Это получение заголовка окна, в нем отображаются процент выполнения копирования
 
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
Это получение заголовка окна, в нем отображаются процент выполнения копирования
Как раз хотел написать про это. Поэкспериментировал. Каждый раз $hTitleProc имеет новое значение. И небольшое наблюдение. Часто не совпадает число процентов. Там на скрине есть две позиции, где отображается бег процентов. В заглавии окна и над самим графиком. Ощущение, что притормаживает передача данных из одной переменной в другую. Раньше такого не замечал. В принципе оно не важно, потому что все равно больше 90%. Но как-то странно. И у меня строго на промежутке 99-100% скринит. А в вашем примере пробовал ставить 99%, скрин вообще не успевает сделаться и в окошко не вставляется.
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
только писать свой процесс копирования. скорость в мегабайах рассчитать можно. если есть желание, то и график нарисовать можно. но как по мне, это лишнее
и все это будет гораздо проще, чем ловить окна и делать приблизительные скрины приблизительных результатов
 
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
только писать свой процесс копирования
Я только неделю пробую писать на autoit. Процесс интересный и даже есть планы через время написать уже для работы скрипт. Ну а потом как пойдет. А пока время поджимает. Другой работы хватает, а скрипт нужен. Вообще подумываю создать тему в столе заказов, где все хотелки в отношении скрипта озвучу, поскольку не понимаю, можно ли тут продолжать. Все хотелки касаются визуализации процесса копирования (вроде по теме), но касаются уже температуры и прочих характеристик.
Сообщение автоматически объединено:

график нарисовать можно
А график нужен для оценки заполняемости буфера винта. Хотя, если знаете способ, как определить размер буфера, то буду признателен
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
на графике, что мы видим при копировании, указывается скорость. то есть, наблюдаем график увеличения или уменьшения скорости копирования
можно показать буфер чтения.(объем потребляемой памяти при цикле копирования)
пример во вложении
вот в этом случае мы полностью все контролируем
буфер жесткого диска это тех.данные. он фиксирован. и по сути, считываемый объем файла идет через буфер диска. но там могут быть и другие данные - теневое копирование других приложений. это с HDD. В SSD все иначе
 

Вложения

  • тест.au3
    15.8 КБ · Просмотры: 7
  • Безымянный.jpg
    Безымянный.jpg
    35.6 КБ · Просмотры: 6
Последнее редактирование:
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
можно показать буфер чтения.(объем потребляемой памяти при цикле копирования)
Посмотрел, но сходу не понял, откуда берется объем буфера. Если чисто методом научного втыка, то как бы я не копировал, в каком бы направлении и на какой бы винт, включая ssd буфер фиксируется на 1мб. Хотя как я понимаю, у моего ssd 128мб.. Опять же, если смотреть на график при копировании через проводник, то в динамике видны изменения скорости. Не просто цифры скачут, а именно запоминаются и отображаются визуально. Поэтому я абсолютно согласен с твоими мыслями, что
на графике, что мы видим при копировании, указывается скорость. то есть, наблюдаем график увеличения или уменьшения скорости копирования
можно показать буфер чтения.(объем потребляемой памяти при цикле копирования)
Именно так и собирался высчитывать. Но не уверен, что у тебя правильно реализовано.
Смотри, Берется промежуток времени, на котором скорость достаточно высокая и мало колеблеться. Умножается на скорость и получается обьем. Конечно, нужно ещё вычесть объем за тот же промежуток на минимальной скорости. Ну это конечно я так понимаю. Возможно ошибочно. Как в твоем варианте реализовано, я пока не понял, но скорее всего не так. Даже с учетом всяких теневых копирований погрешность не должна быть такая большая. У меня на самом простеньком винте буфер 32мб, на двух других -128мб. Могу для пробы ещё пару ssd подкинуть, но думаю результат будет тот же.
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
я показал пример. остальные подсчеты делают дополнительно.
в моем случае буфер, это считанные(записанные данные) за один цикл чтения файла. в коде указано, если файл меньше мегабайта, то читать его весь. значит в буфере будет меньше мегабайта. если больше, то читать по мегабайту, и конечно же, остаток файла будет не мегабайт. вот каждый этот цикл чтение-запись идет через буфер.
отсюда, ты можешь вычислить все что тебе нужно. начальную скорость, среднюю и так далее и тому подобное. это уже математика. создав свой код копирования мы можем регулировать и скорость и количество байт чтение(запись).
Сообщение автоматически объединено:

еще момент. нужно понять логику работы Autoit. рассматривать примеры. с малыми знаниями сложно в короткий срок написать стоящую утилиту. со временем проявляются баги. нужно править и улучшать работу.
сначала очень желательно продумать весь функционал, написать тех.задание. уже потом все это в куче реализовывать. Иначе вполне вероятно будет так, что желая добавить еще один функционал в код придется глобально менять всё.
"давай вот это приклеим в код...а давай еще вот это... а хорошо бы и вот это..." - так кроме угнетения мозга ничего не добьешься ))
 
Последнее редактирование:
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
так кроме угнетения мозга ничего не добьешься
Это точно ))) у меня уже угнетен по самое "не могу" ))) Сперва-то нужно было одно, тупо показать наглядно скорость и приблизительный буфер. А потом стал читать, пробовать и понял, что можно и нужно гораздо больше даже для более корректного отображения скорости копирования. Нашел и пару "программ" для определения некоторых контроллеров. Одним словом - все то, что разбросано по инету и из-за своей разбросанности, узконапрвленности и неудобности малоизвестно.
в коде указано, если файл меньше мегабайта, то читать его весь. значит в буфере будет меньше мегабайта. если больше, то читать по мегабайту, и конечно же, остаток файла будет не мегабайт
Теперь понятно, почему прям видно, как он упирается в 1мб. Гляну внимательней.
создав свой код копирования мы можем регулировать и скорость и количество байт чтение(запись)
Плохо понимаю, как все это фиксировать.
с малыми знаниями сложно в короткий срок написать стоящую утилиту. со временем проявляются баги. нужно править и улучшать работу.
Тут единственное, что меня успокаивает, что это для личного пользования. Хотелось к концу недели показать тест одного винта одному человеку. Но, похоже не судьба. Либо ограничусь "урезаным" функционалом.
Как я понимаю, у него только другой тип памяти, а принцип работы такой же.
сначала очень желательно продумать весь функционал, написать тех.задание. уже потом все это в куче реализовывать.
По сути на данный момент уже есть все в голове. Это раньше оно было разбросанным. Сейчас оформилось и почти не будет меняться. Даже в интерфейсе GUI, думаю, видно . А вот знаний точно не хватает. И очень неудобно свои хотелки на других перегружать. Конечно можно сделать и коммерческий проект, но я точно в нем 5 колесо )))))) пока по крайней мере )))) Поэтому буду для себя потихоньку мучать скрипт и может быть, когда-то получиться что-то стоящее и я буду спасть спокойно ) Для недели занятий autoit уже стало кое-что получаться самостоятельно ) За что всем большое спасибо )
Сообщение автоматически объединено:

если файл меньше мегабайта
Поэкспериментировал с больщим значением. Ставил 128 и 256мб. Есть замечания.
1. Секундомер дергается
2. Буфер показал 256, хотя он 128. Тоесть файл считало полностью, но он не весь сразу считался в буфер. Скорее всего в оперативу компа.
Сообщение автоматически объединено:

все это будет гораздо проще, чем ловить окна и делать приблизительные скрины приблизительных результатов
И ещё небольшая просьба. Можно все таки прикрутить мою функцию скрина? Может тогда пойму некоторые моменты. Да и делает она скрин строго в конце процесса. Проверял. При первом запуске на 100%. При повторных тестах до закрытия окна на 99%. Кстати, не пойму, с чем связано.
Ну и параллельно буду пробовать твою функцию в 4 ячейки вставлять. Если не получиться, то забегу за помощью )
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Поэкспериментировал с больщим значением. Ставил 128 и 256мб. Есть замечания.
1. Секундомер дергается
2. Буфер показал 256, хотя он 128. Тоесть файл считало полностью, но он не весь сразу считался в буфер. Скорее всего в оперативу компа.
ясно дело, куда такие значения. если HDD, то в моем случае его кэш 64мб.
можно до десяти мегабайт считывания сделать.
насчет твоей функции скрина. то не могу понять, как она может так точно делать скрин))
в ней, по сути, только проверка наличия окна и сразу скрин. а как же проценты?
 
Автор
D

DyadyaGenya

Знающий
Сообщения
300
Репутация
10
в ней, по сути, только проверка наличия окна и сразу скрин. а как же проценты?
Видимо просто быстрая реакция компьютера на закрытие окна, быстро комбинацию клавишь отправил ))) Не знаю ))) попробовал, а оно получилось ))) проверь, вставть процесс копирования перед вызовом скрина
Код:
$Shell = ObjCreate('Shell.Application')
$Shell.NameSpace('куда').CopyHere('откуда', 16)
_SCREEN()


можно до десяти мегабайт считывания сделать.
Не совсем понимаю, как это поможет. Ведь получается, что за один цикл читает файл не сразу в буфер, а куда-то минуя. А уже оттуда в буфер.
Цикл чтения ведь зависит не только от того, какой мы ему размер пропишем? Но если только от этого значения, то точно не в буфер.
 
Последнее редактирование:

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Буфер это участок виртуальной памяти. Что оперативка компа, что оперативка hdd.
Насчет скрина, то это не тот вариант, который можно назвать надежным. К тому же, на скрине будет только график скорости. Что можно вычислить чере своою функцию. Ну, если нравятся такие костыли, то почему бы нет. Чтобы это работало в том первом коде, где была запись в файл, то тут нужно заморачиваться. Нужно перенести в файл не только код скрина, но и всех прилагающихся функций GDI+, которые иы используешь
 
Верх