1

Тема: AHK: ProgressBar при копировании иногда пишет Not Responding

Вот фрагмент кода:

      if (StrLen(List)>160)
      {
         Gui, Add, Progress, x6 y40 w460 h20 Range0-%count% vProgress
         Gui, Add, Text, x6 y10 w240 h20 vDo, Идет копирование
         Gui, Show, x229 y182 h87 w477
         List := "", dir := TempFolder
         setformat,integer,hex
         a:= 0x20000
         Loop, parse, PrevList, |
         {
            if (in > A_Index)
               Continue
            b := Chr(a)
            List .= b "|"
            a++
            FileCopy, %A_LoopField%, %TempFolder%\%b%
            GuiControl,, Progress, +1
            if (out = A_Index)
               break
         }
      }

При копировании больших файлов - 4 гига и более, гуи тормозит и при перетаскивании  пишет Not Responding.
Что с этим поделать?

2

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Поставить в цикле задержку (Sleep)?

3 (изменено: Malcev, 2015-09-20 16:56:01)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Нет, дело не в этом.
Попробуйте запустить следующий код и подергайте, поперетаскивайте, покликайте на Gui.

test := "D:\test.txt"
test1 := "D:\test1.txt"
RunWait, C:\Windows\System32\fsutil.exe file createnew %test% 4000000000
Gui, Add, Progress, x6 y40 w460 h20 Range0-%count% vProgress
Gui, Add, Text, x6 y10 w240 h20 vDo, Идет копирование
Gui, Show, x229 y182 h87 w477
FileCopy %test%, %test1%

Есть еще такой код, но тоже тормозит:

file1 := "D:\test.txt"
file2 := "D:\test1.txt"
RunWait, C:\Windows\System32\fsutil.exe file createnew %file1% 4000000000

address := registercallback("update")
dllcall("CopyFileEx",str,file1,str,file2,Uint,address,Uint,0,int,0,int,0)
progress, off

update(var1lo,var1hi,var2lo,var2hi,var3lo,var3hi,var4lo,var4hi,var5,var6,var7,var8,var9)
{
    If (A_PtrSize = 8)
        copied := (var1hi / var1lo) * 100
    Else
        copied := (var2lo/var1lo) * 100
    progress, % copied,,Transfert du fichier !,Copie
    return 0
}

Какие еще есть решения?
Как я понимаю, Виндовс определяет, что скрипт завис и показывает это, хотя скрипт просто занят копированием. Как бы это обойти?

4

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Попробовал. Ну да, GUI не отвечает во время работы AutoHotkey'ной команды FileCopy, независимо от размера файла. Почему бы не использовать стандартную команду COPY?

5

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Точно, как я об этом не подумал?
И главное на официальных форумах такое решение не предлагается.
Спасибо!!!

6 (изменено: Malcev, 2015-09-20 18:07:15)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Рано радовался. Все-равно тормозит:

file1 := "D:\test.txt"
file2 := "D:\test1.txt"
RunWait, C:\Windows\System32\fsutil.exe file createnew %file1% 4000000000
Gui, Add, Progress, x6 y40 w460 h20 Range0-%count% vProgress
Gui, Add, Text, x6 y10 w240 h20 vDo, Идет копирование
Gui, Show, x229 y182 h87 w477

Run, %comspec% /k ,,Hide UseErrorLevel, cPid
WinWait, ahk_pid %cPid%,, 10
DllCall("AttachConsole","uint",cPid)
hCon:=DllCall("CreateFile","str","CONOUT$","uint",0xC0000000,"uint",7,"uint",0,"uint",3,"uint",0,"uint",0)

objShell := ComObjCreate("WScript.Shell")
objExec := objShell.Exec(ComSpec " /C copy """ file1 """ """ file2 """")
strStdOut := ""
while, !objExec.StdOut.AtEndOfStream
   strStdOut := objExec.StdOut.ReadAll()

DllCall("CloseHandle", "uint", hCon)
DllCall("FreeConsole")
Process, Close, %cPid%
Gui, Destroy

Наверное надо как-то блокировать посылку сообщений от виндовса на гуи.

7

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Был такой вариант копирования частями, правда сам не использовал.

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

8

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Спасибо! То есть, существует вероятность, что в коде копирования частями могут быть баги?

9

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Да вроде всё работает, тот коммент касался первой версии, но мне кажется тормоза тоже есть.

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

10

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Тормозов не наблюдается вообще только через вызов стандартного диалога:

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

11

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Malcev пишет:

Рано радовался. Все-равно тормозит

Не понял, почему так хитро использована команда COPY?

Run, %comspec% /c COPY D:\1 C:\2, , Hide

12

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

А я не понял, как оно связано с ProgressBar...

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

13 (изменено: Malcev, 2015-09-20 22:44:04)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Не понял, почему так хитро использована команда COPY?

А я не понял, как оно связано с ProgressBar...

Да, так не тормозит.
По-хитрому, потому что хотел копировать через Robocopy и считывать информацию с cmd для подсчета ProgressBar.
Не знал, что запуск cmd через WScript.Shell будет являться причиной тормозов.

14

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

У меня работает такой пример:

file1:="1.zip"
file2:="2.zip"

address :=registercallback("update")
dllcall("CopyFileEx",str,file1,str,file2,Uint,address,Uint,0,int,0,int,0)

return

Esc::ExitApp
update(var1lo,var1hi,var2lo,var2hi,var3lo,var3hi,var4lo,var4hi,var5,var6,var7,var8,var9){
  progress,% (var2lo/var1lo) * 100,,% (var2lo/var1lo) * 100 " %",copying file
  return 0
}

Источник

15 (изменено: Malcev, 2015-09-21 05:05:20)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Да, знаю этот код. Он тут не совсем верен (не учитывает битность ahk).
Правильный вариант я приводил в 3 посте.
Но для меня он не подходит. Опять глючит Gui.

file1 := "D:\test.txt"
file2 := "D:\test1.txt"
Gui, Add, Progress, x6 y40 w460 h20 Range0-100 vProgress
Gui, Add, Text, x6 y10 w240 h20 vDo, Идет копирование
Gui, Show, x229 y182 h87 w477

address := registercallback("update")
dllcall("CopyFileEx",str,file1,str,file2,Uint,address,Uint,0,int,0,int,0)

update(var1lo,var1hi,var2lo,var2hi,var3lo,var3hi,var4lo,var4hi,var5,var6,var7,var8,var9)
{
    If (A_PtrSize = 8)
        copied := (var1hi / var1lo) * 100
    Else
        copied := (var2lo/var1lo) * 100
    return 0
}

Наверное буду либо экспортировать лог Robocopy и считывать его, либо не заварачиваться и обновлять progress bar по завершению копирования файла.

16

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Если на целевом компьютере установлен AHK, можно показывать окно и производить копирование в разных процессах (один запускает другой).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

17 (изменено: Malcev, 2015-09-21 04:57:58)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Этот вариант уже написал serzh82saratov, но он его не удовлетворил из-за:

Представив дальнейшую отладку для отмены копирования, связи между двумя скриптами и.т.п. хочется отказатся от этой идеи.

http://forum.script-coding.com/viewtopi … 385#p77385
Вот скрипт, на который навел serzh82saratov. Он минимально тормозит, но не может ли случиться, что при больших файлах около 4 гигов могут возникнуть проблемы?

InputFile := "D:\test.txt"
OutputFile := "D:\test1.txt"

Gui, Add, Progress, x6 y40 w460 h20 Range0-100 vProgress
Gui, Add, Text, x6 y10 w240 h20 vDo, Идет копирование
Gui, Show, x229 y182 h87 w477
Source := FileOpen(InputFile, "r")
Dest := FileOpen(OutputFile, "w")
Incr := Ceil(Source.Length / 100)
    
while not Source.AtEOF {
   Source.RawRead(Data, Incr)
   Dest.RawWrite(Data, Incr)
   GuiControl,, Progress, +1
}
    
Source.Close()
Dest.Close()
return

18

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

при больших файлах около 4 гигов могут возникнуть проблемы?

На 4 гигах не будет. Но больщие объёмы надо делить не на 100, а задать буфер в один\несколько мегабайт, Progress обновлять конечно не на каждой итерации (очень долго будет), а по процентам.

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

19

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

На счет прогресса потом разберусь.
А с буффером я не напортачил?


Gui, Add, Progress, x6 y40 w460 h20 Range0-100 vProgress
Gui, Add, Text, x6 y10 w240 h20 vDo, Идет копирование
Gui, Show, x229 y182 h87 w477
bufSize := 2000000
VarSetCapacity(buf, bufSize)
loop 5
{
   InputFile := "C:\" A_Index ".txt"
   OutputFile := "D:\" A_Index ".txt"
   Source := FileOpen(InputFile, "r")
   Dest := FileOpen(OutputFile, "w")

   while not Source.AtEOF {
      Source.RawRead(&buf, bufSize)
      Dest.RawWrite(&buf, bufSize)
      GuiControl,, Progress, +1
   }
}

Source.Close()
Dest.Close()
VarSetCapacity(buf, 0)
return

20

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Думаю нет.

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

21 (изменено: Malcev, 2015-09-22 09:47:41)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Вот еще один вариант:
Можно копировать через Robocopy и захватывать информацию с CMD с помощью:
http://www.autohotkey.com/board/topic/9 … douttovar/

22 (изменено: teadrinker, 2015-09-22 14:50:32)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

До кучи асинхронное копирование:

CopyFile.Start( "source.txt"   ; путь к файлу 
               , "dest.txt"    ; путь копирования
               , 250           ; ширина прогрессбара
               , 400           ; x-координата окна
               , 300 )         ; y-координата окна
               
ExitApp

class CopyFile
{
   Start(source, dest, w = 300, x = "", y = "")  {
      this.end := 0
      if FileExist(dest)  {
         MsgBox, 0x34,, Файл "%dest%" уже существует.`nПерезаписать?
         IfMsgBox, No
            Return
      }
      Gui, New, +hwndhGui
      this.hGui := hGui
      Gui, Margin,, 10
      Gui, Add, Progress, w%w% h20 -Smooth, 0
      Gui, Add, Button, gCancelCopy x+-80 y+10 w80, Cancel
      Gui, Show, % (x != "" && y != "") ? "x" x " y" y : "", Идёт копирование...
      
      OnMessage(DllCall("RegisterWindowMessage", Str, "WM_INFO"), "WM_INFO")
      this.CopyPID := ExecScript(this.GetScript(source, dest))
      OnExit("CancelCopy") 
      while !this.end
         Sleep, 500
   }
   
   GetScript(source, dest)  {
      CopyScript =
      (
         #NoTrayIcon
         ERROR_REQUEST_ABORTED := 1235, COPY_FILE_NO_BUFFERING := 0x1000
         source := "%source%", dest := "%dest%"
         WM_INFO := DllCall("RegisterWindowMessage", Str, "WM_INFO")
         DetectHiddenWindows, On
         WinWait, ahk_id %A_ScriptHwnd%
         VarSetCapacity(cancel, 4, 0)
         PostMessage, WM_INFO, 1, &cancel
         
         addr := RegisterCallback("ProgressControl", "F", 4, WM_INFO)
         FileGetSize, size, `% source, M
         if !DllCall("CopyFileEx", Str, source, Str, dest, Ptr, addr, Ptr, 0, Ptr, &cancel, UInt, size > 1024 ? COPY_FILE_NO_BUFFERING : 0)
            PostMessage, WM_INFO, 0, A_LastError = ERROR_REQUEST_ABORTED ? 0 : A_LastError
         else
            PostMessage, WM_INFO, 3
         ExitApp
         
         ProgressControl(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred)  {
            PostMessage, A_EventInfo, 2, Round((A_PtrSize = 8 ? TotalBytesTransferred : StreamSize)/TotalFileSize * 100)
         }
      )
      Return CopyScript
   }
}

CancelCopy()
{
   static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20
   Process, Exist, % CopyFile.CopyPID
   if !ErrorLevel
      Return
   
   hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_WRITE, Int, 0, UInt, CopyFile.CopyPID, Ptr)
   DllCall("WriteProcessMemory", Ptr, hProc, Ptr, CopyFile.CancelPtr, UIntP, 1, Ptr, 4, PtrP, Written)
   DllCall("CloseHandle", Ptr, hProc)
   OnExit("CancelCopy", 0)
}

WM_INFO(wp, lp)
{
   Critical
   Gui, % CopyFile.hGui ":Default"
   if (wp = 1)
      CopyFile.CancelPtr := lp
   
   if (wp = 2)  {
      GuiControl,, msctls_progress321, % lp
      Gui, Show, NA, % "Идёт копирование... " . lp . "%"
   }
   if (wp = 0 && lp = 0)  {
      GuiControl,, msctls_progress321, 0
      Gui, Show, NA, Отменено
      Sleep, 1000
      Gui, Destroy
   }
   if (wp = 0 && lp != 0)  {
      GuiControl,, msctls_progress321, 0
      Gui, Show, NA, Ошибка
      MsgBox, 16, Error, Ошибка копирования %lp%
      Gui, Destroy
   }
   if (wp = 3)  {
      GuiControl,, msctls_progress321, 100
      Gui, Show, NA, Успешно завершено
      Sleep, 1000
      Gui, Destroy
   }
   if wp in 0,3
      OnExit("CancelCopy", 0), CopyFile.end := 1
}

ExecScript(Script)
{
   shell := ComObjCreate("WScript.Shell")
   exec := shell.Exec(A_AhkPath " *")
   exec.StdIn.Write(script)
   exec.StdIn.Close()
   return exec.ProcessID
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

23

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

teadrinker
Гуд, только по окончанию надо бы убирать прогресс вместе со скриптом из трея, клавиша не назначена всё равно.

24

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Почему, это ведь не самостоятельный скрипт, это просто функция для копирования, которую можно вставить куда угодно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

25

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Ну, какая разница? Так поведенчески логичней.

26

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Подправил немного.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

27 (изменено: teadrinker, 2015-09-22 17:17:32)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Или так всё-таки, не знаю, как лучше.

CopyFile.Start( "source.txt"   ; путь к файлу 
               , "dest.txt"    ; путь копирования
               , 250           ; ширина прогрессбара
               , 400           ; x-координата окна
               , 300 )         ; y-координата окна

while !CopyFile.end
   Sleep, 500
ExitApp

class CopyFile
{
   Start(source, dest, w = 300, x = "", y = "")  {
      this.end := 0
      if FileExist(dest)  {
         MsgBox, 0x34,, Файл "%dest%" уже существует.`nПерезаписать?
         IfMsgBox, No
            Return,, this.end := 1
      }
      Gui, New, +hwndhGui
      this.hGui := hGui
      Gui, Margin,, 10
      Gui, Add, Progress, w%w% h20 -Smooth, 0
      Gui, Add, Button, gCancelCopy x+-80 y+10 w80, Cancel
      Gui, Show, % (x != "" && y != "") ? "x" x " y" y : "", Идёт копирование...
      
      OnMessage(DllCall("RegisterWindowMessage", Str, "WM_INFO"), "WM_INFO")
      this.CopyPID := ExecScript(this.GetScript(source, dest))
      OnExit("CancelCopy")
   }
   
   GetScript(source, dest)  {
      CopyScript =
      (
         #NoTrayIcon
         ERROR_REQUEST_ABORTED := 1235, COPY_FILE_NO_BUFFERING := 0x1000
         source := "%source%", dest := "%dest%"
         WM_INFO := DllCall("RegisterWindowMessage", Str, "WM_INFO")
         DetectHiddenWindows, On
         WinWait, ahk_id %A_ScriptHwnd%
         VarSetCapacity(cancel, 4, 0)
         PostMessage, WM_INFO, 1, &cancel
         
         addr := RegisterCallback("ProgressControl", "F", 4, WM_INFO)
         FileGetSize, size, `% source, M
         if !DllCall("CopyFileEx", Str, source, Str, dest, Ptr, addr, Ptr, 0, Ptr, &cancel, UInt, size > 1024 ? COPY_FILE_NO_BUFFERING : 0)
            PostMessage, WM_INFO, 0, A_LastError = ERROR_REQUEST_ABORTED ? 0 : A_LastError
         else
            PostMessage, WM_INFO, 3
         ExitApp
         
         ProgressControl(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred)  {
            PostMessage, A_EventInfo, 2, Round((A_PtrSize = 8 ? TotalBytesTransferred : StreamSize)/TotalFileSize * 100)
         }
      )
      Return CopyScript
   }
}

CancelCopy()
{
   static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20
   Process, Exist, % CopyFile.CopyPID
   if !ErrorLevel
      Return
   
   hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_WRITE, Int, 0, UInt, CopyFile.CopyPID, Ptr)
   DllCall("WriteProcessMemory", Ptr, hProc, Ptr, CopyFile.CancelPtr, UIntP, 1, Ptr, 4, PtrP, Written)
   DllCall("CloseHandle", Ptr, hProc)
   OnExit("CancelCopy", 0)
}

WM_INFO(wp, lp)
{
   Critical
   Gui, % CopyFile.hGui ":Default"
   if (wp = 1)
      CopyFile.CancelPtr := lp
   
   if (wp = 2)  {
      GuiControl,, msctls_progress321, % lp
      Gui, Show, NA, % "Идёт копирование... " . lp . "%"
   }
   if (wp = 0 && lp = 0)  {
      GuiControl,, msctls_progress321, 0
      Gui, Show, NA, Отменено
      Sleep, 1000
      Gui, Destroy
   }
   if (wp = 0 && lp != 0)  {
      GuiControl,, msctls_progress321, 0
      Gui, Show, NA, Ошибка
      MsgBox, 16, Error, Ошибка копирования %lp%
      Gui, Destroy
   }
   if (wp = 3)  {
      GuiControl,, msctls_progress321, 100
      Gui, Show, NA, Успешно завершено
      Sleep, 1000
      Gui, Destroy
   }
   if wp in 0,3
      OnExit("CancelCopy", 0), CopyFile.end := 1
}

ExecScript(Script)
{
   shell := ComObjCreate("WScript.Shell")
   exec := shell.Exec(A_AhkPath " *")
   exec.StdIn.Write(script)
   exec.StdIn.Close()
   return exec.ProcessID
}

Так можно параллельно с копированием делать что-то ещё.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

28

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Пытался выполнить код, что сообщением выше, но не получилось. Не подскажите в чем дело?

(7) : ==> The following variable name contains an illegal character:
"CopyFile.end"

29

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Обновите AHK.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

30 (изменено: unKn0wn, 2015-09-25 22:08:00)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Точно, спасибо. Для тех, кто столкнётся, с проблемой при запуске: Autohotkey_L

Всё-же рано радовался, теперь мне скрипт пишет, что autohotkey не является приложением win32 -хотя, я устанавливал версию 32 unicod.

31

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Любой код на форуме пишется в расчёте на самую последнюю версию AHK.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

32

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

скрипт пишет, что autohotkey не является приложением win32

Переустановите ещё раз с помощью инсталлера, смотрите внимательно, что устанавливаете.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

33 (изменено: unKn0wn, 2015-09-25 23:36:23)

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Скачал инсталлер по приведённой мною ссылке, запустил его-modify-32 unicod. Проблема осталась.

34

Re: AHK: ProgressBar при копировании иногда пишет Not Responding

Почитайте здесь. Возможно, какая-то из описанных проблем.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder