Что нового

Пауза интерпретатора скрипта

Guezt

Продвинутый
Сообщения
335
Репутация
82
Собственно вопрос в том, что я так и не нашел как вызвать паузу, аналогичную той, что по клику на значок скрипта трее происходит, как можно реализовать аналогичную паузу по горячей клавише? или вызвать ее в теле скрипта? ведь пауза, которая используется самим интерпретатором действительно ставит скрипт на паузу именно в любой точке выполнения скрипта и продолжает от туда же по снятию с паузы.
 

dwerf

Использует ArchLinux
Сообщения
478
Репутация
219
Из английского хелпа, пауза на соответствующей кнопке
Код:
; Press Esc to terminate script, Pause/Break to "pause"

Global $Paused
HotKeySet("{PAUSE}", "TogglePause")
HotKeySet("{ESC}", "Terminate")
HotKeySet("+!d", "ShowMessage")  ;Shift-Alt-d

;;;; Body of program would go here ;;;;
While 1
    Sleep(100)
WEnd
;;;;;;;;

Func TogglePause()
    $Paused = NOT $Paused
    While $Paused
        sleep(100)
        ToolTip('Script is "Paused"',0,0)
    WEnd
    ToolTip("")
EndFunc

Func Terminate()
    Exit 0
EndFunc

Func ShowMessage()
    MsgBox(4096,"","This is a message.")
EndFunc
 
Автор
G

Guezt

Продвинутый
Сообщения
335
Репутация
82
dwerf
Если не сложно "ткни пальцем" в раздел справки где это написано. :smile:


Добавлено:
Сообщение автоматически объединено:

да действительно идет прерывание и возобновление выполнения скрипта добавил функцию в чем собственно и убедился:
Код:
; Press Esc to terminate script, Pause/Break to "pause"

Global $Paused
HotKeySet("{PAUSE}", "TogglePause")
HotKeySet("{END}", "Terminate")
HotKeySet("+!d", "ShowMessage")  ;Shift-Alt-d

;;;; Body of program would go here ;;;;
While 1
	_test()
    Sleep(100)
WEnd
;;;;;;;;

Func TogglePause()
	ConsoleWrite("paused"&@CR)
    $Paused = NOT $Paused
    While $Paused
        sleep(100)
        ToolTip('Script is "Paused"',0,0)
    WEnd
    ToolTip("")
EndFunc

Func Terminate()
    Exit 0
EndFunc

Func ShowMessage()
    MsgBox(4096,"","This is a message.")
EndFunc


Func _test()
	for $i=0 to 5
		ConsoleWrite($i&@CR)
		Sleep(3000)
	Next
EndFunc
спасибо :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Guezt
Код:
HotKeySet()
 

dwerf

Использует ArchLinux
Сообщения
478
Репутация
219
Можно, это пример применения функции HotKeySet().
AutoIt->Function Reference->Keyboard Management->HotKeySet

Кстати в справке слева есть закладка "поиск".
 
Автор
G

Guezt

Продвинутый
Сообщения
335
Репутация
82
dwerf [?]
Кстати в справке слева есть закладка "поиск".
не ищет :( MsgBox выходит типа title Справка text разделы не найдены... использую стандартный английский хелп с последней версии autoit 3.3.6.1.


Добавлено:
Сообщение автоматически объединено:

Ну а полную паузу никак не реализовать ? никто не знает ? я имею ввиду что данный вид паузы запросто перебивает функция через
Код:
AdlibRegister()


или в опцию паузы добавлять
Код:
AdlibUnRegister()

а по снятию с паузы опять активировать ?!
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Guezt [?]
полную паузу никак не реализовать ? никто не знает ? я имею ввиду что данный вид паузы запросто перебивает функция через
У меня получилось вот так (используется “замораживание” процесса):

Код:
; Press Esc to terminate script, Pause/Break to "pause"

#OnAutoItStartRegister "OnScriptStart"

Global $iPID

HotKeySet("{PAUSE}", "TogglePause")
HotKeySet("{ESC}", "Terminate")
HotKeySet("^+!r", "ResumePause")

AdlibRegister("Callback")

While 1
    Sleep(100)
WEnd

Func TogglePause()
	If Not StringInStr($CmdLineRaw, "/SuspendProcess=") Then
		ToolTip('Script is "Paused"', 0, 0)
		HotKeySet("{PAUSE}")
		Run(@AutoItExe & ' "' & @ScriptFullPath & '" /SuspendProcess=' & @AutoItPID)
	Else
		HotKeySet("{PAUSE}")
		_WinAPI_SuspendProcess($iPID, False)
		Send("^+!r") ;Will call ResumePause() in the original (parent) process
		Terminate()
	EndIf
EndFunc

Func ResumePause()
	ToolTip("")
	HotKeySet("{PAUSE}", "TogglePause")
EndFunc

Func OnScriptStart()
	If Not StringInStr($CmdLineRaw, "/SuspendProcess=") Then
		Return
	EndIf
	
	Opt("TrayIconHide", 1)
	
	Global $iPID = StringRegExpReplace($CmdLineRaw, "(?i).*/SuspendProcess=(\d+).*", "\1")
	
	_WinAPI_SuspendProcess($iPID, True)
	HotKeySet("{PAUSE}", "TogglePause")
	
	While 1
		Sleep(100)
	WEnd
EndFunc

Func Terminate()
    Exit 0
EndFunc

Func Callback()
	ConsoleWrite(".")
EndFunc

Func _WinAPI_SuspendProcess($iPID, $bSuspend = True)
	$iPID = ProcessExists($iPID)
	
	If Not $iPID Then
		Return SetError(1, 0, 0)
	EndIf
	
	Local $aNtSuspResumProc
	Local $ah_OpProcess = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', 0, 'int', $iPID)
	
	If $bSuspend Then
		$aNtSuspResumProc = DllCall("ntdll.dll", "int", "NtSuspendProcess", "int", $ah_OpProcess[0])
	Else
		$aNtSuspResumProc = DllCall("ntdll.dll", "int", "NtResumeProcess", "int", $ah_OpProcess[0])
	EndIf
	
	DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $ah_OpProcess)
	
	If IsArray($aNtSuspResumProc) Then
		Return 1
	EndIf
	
	Return SetError(2, 0, 0)
EndFunc
 

tech-gs

Знающий
Сообщения
54
Репутация
5
Есть один вопрос. Если скрипт запускает на выполнение другую программу или командный файл, то для полноценной реализации паузы придется тормозить еще и их.
Ниже приведен несколько измененный скрипт (из него убран код, касающийся приостановки самого скрипта), который для создания архива (по Alt+A) запускает консольную версию архиватора 7z. Через _WinAPI_SuspendProcess() успешно получается приостановить работу архиватора.
Но как все это тормознуть, если архиватор запускается через Run(@COMSPEC & ' /C "..." ') ? (для этого в скрипте нужно раcкоментировать 3-ю строку в функции ArcProcess_Create())
На возможный вопрос: А зачем через Run(@COMSPEC & ' /C "..." ') - отвечу что так нужно, т.к. команда архивации, а точнее набор выполняемых инструкций в DOS-сессии, формируются динамически и без @COMSPEC не обойтись.

Код:
; Press Esc to terminate script, Pause to pause/resume process
; Alt+A - запуск процесса (который и будем тормозить)

Global $iPIDProc
Global $Pause = 0

Global $sToggleFunc
	$sToggleFunc = "ArcProcess_TogglePause"

HotKeySet("{PAUSE}", $sToggleFunc)
HotKeySet("{ESC}", "Terminate")

Global $sProcCreateFunc
	$sProcCreateFunc = "ArcProcess_Create"

HotKeySet("!a", $sProcCreateFunc) ; Alt+A - Горячая клавиша запуска процесса создания архива (который и будем тормозить)
HotKeySet("!ф", $sProcCreateFunc)

AdlibRegister("Callback")

While 1
	Sleep(100)
WEnd


Func ArcProcess_Create()
Local $Arc = @ScriptDir & '\Test.7z'
Local $ArcCmd = '"' & @ProgramFilesDir & '\7-Zip\7z.exe" a "' & $Arc & '" -t7z -m0=BCJ -m1=LZMA:d=26 -mx=9 -mhc=on -ms=on -mmt=on "' & @WindowsDir & '\Help\*"'
	;$ArcCmd = '"' & @COMSPEC & '" /C "@echo off && @title CMD - Create archive && @echo. && ' & $ArcCmd & ' && @echo. && @echo Pause 5 sec ... && @ping -n 5 localhost > nul && @echo. "'

	If FileExists ($Arc) Then FileDelete ($Arc)
	$iPIDProc = Run($ArcCmd, '', @SW_SHOW)
	ConsoleWrite(@CRLF & "+> " & @ScriptLineNumber & "  " & $sProcCreateFunc & "() +> Run process: PIDProc = " & $iPIDProc & "; Error - " & @error & @CRLF & "+>     cmd - " & $ArcCmd & @CRLF)
EndFunc

Func ArcProcess_TogglePause()
Local $ret
	If $Pause = 0 Then
		ConsoleWrite(@CRLF & "+> " & @ScriptLineNumber & "  " & $sToggleFunc & "() -> _WinAPI_SuspendProcess() ")
		$ret = _WinAPI_SuspendProcess($iPIDProc, True)
		If $ret = 1 Then
			ToolTip('Process is "Paused"', 0, 0)
			$Pause = 1
		EndIf
	Else
		ConsoleWrite(@CRLF & "+> " & @ScriptLineNumber & "  " & $sToggleFunc & "() -> _WinAPI_SuspendProcess() ")
		_WinAPI_SuspendProcess($iPIDProc, False)
		ToolTip("")
		$Pause = 0
	EndIf
EndFunc

Func Terminate()
	ConsoleWrite(@CRLF & "+> " & @ScriptLineNumber & "  Terminate()" & @CRLF)
    Exit 0
EndFunc

Func Callback()
	If $Pause = 0 Then ConsoleWrite(".")
EndFunc

Func _WinAPI_SuspendProcess($iPID, $bSuspend = True)
	$iPID = ProcessExists($iPID)

	If Not $iPID Then
		ConsoleWrite(@CRLF & "!> " & @ScriptLineNumber & "  _WinAPI_SuspendProcess(" & $iPID & ", " & $bSuspend & ") -> WARNING: Process " & $iPID & " not exist" & @CRLF)
		Return SetError(1, 0, 0)
	EndIf

	Local $aNtSuspResumProc
	Local $ah_OpProcess = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', 0, 'int', $iPID)

	If $bSuspend Then
		$aNtSuspResumProc = DllCall("ntdll.dll", "int", "NtSuspendProcess", "int", $ah_OpProcess[0])
	Else
		$aNtSuspResumProc = DllCall("ntdll.dll", "int", "NtResumeProcess", "int", $ah_OpProcess[0])
	EndIf

	DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $ah_OpProcess)

	If IsArray($aNtSuspResumProc) Then
		ConsoleWrite(@CRLF & "-> " & @ScriptLineNumber & "  _WinAPI_SuspendProcess(" & $iPID & ", " & $bSuspend & ") -> Process is " & StringLeft("'Paused' ", 30*($bSuspend=True)) & StringLeft("'Resumed'" & @CRLF, 30*($bSuspend=False)))
		Return 1
	EndIf

	ConsoleWrite(@CRLF & "!> " & @ScriptLineNumber & "  _WinAPI_SuspendProcess(" & $iPID & ", " & $bSuspend & ") - ERROR ")
	Return SetError(2, 0, 0)
EndFunc
 
Верх