Что нового

Читать информацию из вывода консольного 7z и выводить ее в свой GUI.

gora

Знающий
Сообщения
315
Репутация
19
При архивировании консольный архиватор 7z отображает окно, подобное этому:
consol4.png


В последней строке всегда показывается "процент выполнения" команды архивирования (на скриншоте 23%).

Можно ли и как считывать это значение и выводить его в своем GUI в ходе операции архивирования? Консольное окно архиватора, при этом, лучше скрыть.

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

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
http://autoit-script.ru/index.php/topic,11476.msg75348.html#msg75348
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
joiner
А Вы сами пробовали варианты из той темы применительно к моей задаче? Получилось?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
действие отображения сообщений из cmd в функции
WM_COPYDATA
в том скрипте, на который ссылка.
в функции WM_COPYDATA мы видим
Код:
Case 1 ; "/id:1"
     _GUICtrlEdit_InsertText($Edit1, DllStructGetData($tData, 1))
 Case 2 ; "/id:2"
     _GUICtrlEdit_InsertText($Edit2, DllStructGetData($tData, 1))

команды выведения в окно программы, того, что творится в комстроке. что мешает вывести результат как лейбл, откинув все не нужное?
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
joiner [?]
в том скрипте, на который ссылка
По Вашей ссылке я попадаю на пост madmasles, в нем ссылка на пост Yashied (http://autoit-script.ru/index.php/topic,3768.msg27342.html#msg27342) Вы этот скрипт имеете ввиду?
Его вариант я пробовал, там проценты не выводятся вообще! Вот я и спрашиваю Вас:
gora [?]
Вы сами пробовали варианты из той темы применительно к моей задаче? Получилось?
Если получилось, то приведите, пожалуйста, работающий пример кода.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
gora
ты прав. к сожалению проценты не выводит. только список файлов. можно вместо процентов показывать имена файлов, которые отображает 7z при добавлении в архив.


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

я подобное делал для управления программой sdelete http://autoit-script.ru/index.php/topic,11307.0.html
только не считывал с комстроки, а передавал команды с данными программе sdelete, отображая эту информацию в трее.
можно и в твоем случае так же. 7z может добавлять в архив. создаешь архив и докидываешь туда файлы, если это архивация нескольких файлов или папок, при этом отображая их названия. можно потом будет прикрутить общий прогресс в процентах. известно сколько файлов нужно архивировать это будет 100% и сколько прошло архивацию на данный момент - это текущий прогресс в процентах
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
в принципе то же самое. отображает не проценты а очередной файл упаковки.


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

gora
тут прочитал кое что..не понятны твои мучения. у тебя ж вроде как есть вариант с процентами и прогрессом? http://forum.oszone.net/thread-83838.html
или это муляж? :smile:
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
madmasles
Огромное спасибо, то, что надо! :ok:
joiner [?]
в принципе то же самое. отображает не проценты а очередной файл упаковки.
Совсем не "тоже самое". Поместите для проверки в папку один большой файл, (например, iso образ Windows) и посмотрите. Проценты то изменяются, а файл всего один! ;)

не понятны твои мучения. у тебя ж вроде как есть вариант с процентами и прогрессом?
Мне нужно убрать консольное окно в режиме "упаковки файлов\папок консольным архиватором", а Вы о чем?
 

joiner

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

gora

Знающий
Сообщения
315
Репутация
19
По предложенной madmasles ссылке взял скрипт и прикрутил его к своему окну, слегка подредактировав под свои задачи. Получил следующее:
Код:
#include <APIConstants.au3>
#include <File.au3>
#include <StaticConstants.au3>

Dim $arrayCmdLin,$iPID,$sizeSelect,$widthWind

; файл список в кодировке WIN (1251). У меня он содержит одну строку (но может быть и несколько):
; x:\1
; в этой папке различные файлы и подпапки с файлами общим размером около 50 МБ
$fileList=@ScriptDir&"\List.txt"

; путь и имя выходного архива
$nameArchv="x:\"&@HOUR&"_"&@MIN&"_"&@SEC&"_test.7z"

; путь к архиватору
$p7z='C:\Program Files\7-Zip\'

; вспомогательные переменные для сжатия
$mtd='LZMA2'; метод сжатия
$dct=8; словарь в МБ 
$comline7z='-scsWIN -mmt2 -m0=BCJ2 -m1='&$mtd&':d'&$dct&'m -m2='&$mtd&':d21 -m3='&$mtd&':d21 -mb0:1 -mb0s1:2 -mb0s2:3'

;	расчет размера выделенных папок\файлов
_FileReadToArray($fileList,$arrayCmdLin)
For $i=1 To $arrayCmdLin[0]
	If StringInStr(FileGetAttrib($arrayCmdLin[$i]),'D') Then
		$sizeSelect+=DirGetSize($arrayCmdLin[$i])
	Else
		$sizeSelect+=FileGetSize($arrayCmdLin[$i])
	EndIf
Next
;************************************************************************************

$Title='Архивирование папок/файлов'
$Text='Размер выделенных папок/файлов|' _
	&StringRegExpReplace($sizeSelect,'(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))','\1 ')&@LF& _
	'Выбранный размер словаря (МБ)|'&$dct&@LF& _
	'Выбранный метод сжатия|'&$mtd&@LF& _
	'Имя архива|'&StringRegExpReplace($nameArchv,'^.*\\','')&@LF&@LF& _
	'Для прерывания архивирования нажмите клавишу ESC'&@LF& _
	'Свернуть/развернуть окно можно, нажав клавишу F11'
HotKeySet("{ESC}","_ESC_1")
HotKeySet('{F11}','_F11_1')
$hGuiWin=GUICreate('',0,0)
Opt('MouseCoordMode',2)
GUISetFont(8.5,800,0,'Tahoma')
GUICtrlCreateLabel('',0,0)
;	расчет размеров окна
$array=StringSplit($Text,@LF,2)
$heightWind=UBound($array)*16+20
For $i In $array
	$Width=_GetTabbedStringSizeEx(-1,$i)
	If $Width > $widthWind Then $widthWind=$Width
Next
$widthWind +=20
;	создание окна
$hGuiWin=GUICreate($Title,$widthWind+6,$heightWind+67,-1,-1,$WS_SYSMENU,-1)
GUISetFont(8.5,400,0,'Tahoma')
;	вывод текста
For $i=0 To UBound($array)-1
	$subline=StringSplit($array[$i],'|',1)
	If $i < UBound($array)-3 Then
		GUICtrlCreateLabel($subline[1],50,10+16*$i,_GetTabbedStringSizeEx(-1,$subline[1]),20)
		If $subline[0] > 1 Then
			$Width=_GetTabbedStringSizeEx(-1,$subline[2])
			GUICtrlCreateLabel($subline[2],$widthWind-$Width-10,10+16*$i,$Width,20,$SS_RIGHT)
		EndIf
	Else
		GUICtrlCreateLabel($subline[1],10,10+16*$i,_GetTabbedStringSizeEx(-1,$subline[1]),20)
		GUICtrlSetColor(-1,0xff0000)
		GUICtrlSetFont(-1,8.5,800)
	EndIf
Next
;	вывод иконки и звука
GUICtrlCreateIcon('user32.dll',4+100,10,10)
DllCall('user32.dll','int','MessageBeep','int',0x40)
;	прогрессбар и процент архивирования
$Progress=GUICtrlCreateProgress(10,$heightWind-5,$widthWind-20,20,1)
$Label=GUICtrlCreateLabel('0%',-1,$heightWind+20,$widthWind-20,20,1)
GUICtrlSetFont(-1,-1,800)
GUISetState(BitAND(@SW_DISABLE,@SW_SHOW),$hGuiWin)
;	запуск процесса архивирования
$errr=_7zRead('"'&$p7z&'7z.exe" a "'&$nameArchv&'" @"'&$fileList&'" '&$comline7z,$Progress,$Label,@SW_SHOW)
GUIDelete($hGuiWin)
Exit
;=======================================================================

;main UDF ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;   Function:       _7zRead
;   Description:    Reads progress from 7zip window and sets control data
;   Parameters:     $sCmd = 7zip Commandline to be executed
;                   $iProgress = ControlID of Progress Control to be updated
;                   $iStatic = ControlID of a Static Control (label, button etc pp) to be updated
;                   $nShow = [optional] Flag for 7zip window, default is @SW_HIDE
;   Author:         jennico, basic script by valik

Func _7zRead($sCmd, $iProgress, $iStatic, $nShow=@SW_HIDE)
	$iPID=Run($sCmd,"",$nShow)
	ProcessWait($iPID)
	; Open the 7-Zip percent reader.
	Local $hPercent=Open7ZipPercent($iPID)
	Local $opercent=-1
	; Loop on the process existence.
	While ProcessExists($iPID)
		; Read the percent and update the progress bar.
		Local $nPercent=Read7ZipPercent($hPercent)
		If $nPercent >= 0 And $opercent <> $nPercent Then
			GUICtrlSetData($iProgress,$nPercent)
			GUICtrlSetData($iStatic,$nPercent&"%")
			$opercent=$nPercent
		Else
			Sleep(50)
		EndIf
	WEnd
;	===== Тестовое окно ======
MsgBox(1+256,'Якорь','@error='&@error)
;	===== Тестовое окно ======
	; Cleanup.
	If UBound($hPercent)=4 Then
		; Detach the console
		DllCall('Kernel32.dll','int',"FreeConsole")
		; Destroy the handle
		$hPercent=0
	EndIf
EndFunc	;==>_7zRead

;internal helper functions ++++++++++++++++++++++++++++++++++++++++++++++++++++
Func Open7ZipPercent($pid)
	; Try to attach to the console of the PID.
	; Return 0 on failure.
	If _AttachConsole($pid)=0 Then Return 0
	; The user should treat this as an opaque handle, but internally it contains a handle and some structures.
	Local $vHandle[4]

	$vHandle[0]=_GetStdHandle(-11)	; STDOUT Handle
	$vHandle[1]=DllStructCreate("short dwSizeX;short dwSizeY;short dwCursorPositionX;short dwCursorPositionY;short wAttributes;short Left;short Top;short Right;short Bottom;short dwMaximumWindowSizeX;short dwMaximumWindowSizeY")	; Screen Buffer structure
	$vHandle[2]=DllStructCreate("dword[4]")	; Data buffer
	$vHandle[3]=DllStructCreate("short Left;short Top;short Right;short Bottom")	; SMALL_RECT structure
	; Return the handle on success.
	Return $vHandle
EndFunc	;==>Open7ZipPercent

Func Read7ZipPercent(ByRef $vHandle)
	; Basic sanity check to validate the handle.
	If UBound($vHandle)=4 Then
		; Try to get the screen buffer information.
		If _GetConsoleScreenBufferInfo($vHandle[0],$vHandle[1]) Then
			; Load the SMALL_RECT with the projected text position.
			DllStructSetData($vHandle[3],"Left",DllStructGetData($vHandle[1],"dwCursorPositionX")-4)
			DllStructSetData($vHandle[3],"Top",DllStructGetData($vHandle[1],"dwCursorPositionY"))
			DllStructSetData($vHandle[3],"Right",DllStructGetData($vHandle[1],"dwCursorPositionX"))
			DllStructSetData($vHandle[3],"Bottom",DllStructGetData($vHandle[1],"dwCursorPositionY"))
			; Read the console output.
			If _ReadConsoleOutput($vHandle[0],$vHandle[2],$vHandle[3]) Then
				; This variable holds the output string.
				Local $sPercent=""
				; We iterate over 3 characters because that's all we read.
				For $i = 0 To 3
					Local $pCharInfo=DllStructCreate("wchar UnicodeChar;short Attributes", _
						DllStructGetPtr($vHandle[2])+($i*4))
					; Append the character. Добавьте символ.
					$sPercent &=DllStructGetData($pCharInfo,"UnicodeChar")
				Next
				; Ensure we read a valid percentage.  If so return the cast to a number.
				If StringRight($sPercent,1)="%" Then Return Number($sPercent,4)
			EndIf
		EndIf
	EndIf
	; On failure we return -1 which is obviously not a valid percentage.
	Return -1
EndFunc	;==>Read7ZipPercent

Func _GetStdHandle($nHandle)
	Local $aRet=DllCall('Kernel32.dll','hwnd',"GetStdHandle",'dword',$nHandle)
	If @error Then Return SetError(@error,@extended,-1)
	Return $aRet[0]
EndFunc	;==>_GetStdHandle

Func _AttachConsole($nPid)
	Local $aRet=DllCall('Kernel32.dll','int',"AttachConsole",'dword',$nPid)
	If @error Then Return SetError(@error,@extended,False)
	Return $aRet[0]
EndFunc	;==>_AttachConsole

Func _GetConsoleScreenBufferInfo($hConsoleOutput,$pConsoleScreenBufferInfo)
	Local $aRet=DllCall('Kernel32.dll','int',"GetConsoleScreenBufferInfo",'hwnd',$hConsoleOutput,'ptr', _
		_SafeGetPtr($pConsoleScreenBufferInfo))
	If @error Then Return SetError(@error,@extended,False)
	Return $aRet[0]
EndFunc	;==>_GetConsoleScreenBufferInfo

Func _ReadConsoleOutput($hConsoleOutput,$pBuffer,$pSmallRect);,65540,0,
	; We lie about the types for the COORD structures.  Since they are the size of an int we expect a packed
	; int.  Otherwise we may crash or just pass garbage.
	Local $aRet=DllCall('Kernel32.dll','int',"ReadConsoleOutputW",'ptr',$hConsoleOutput, _
		'ptr',_SafeGetPtr($pBuffer),'int',65540, 'int',0, _
		'ptr',_SafeGetPtr($pSmallRect))
	If @error Then SetError(@error,@extended,False)
	Return $aRet[0]
EndFunc	;==>_ReadConsoleOutput

Func _SafeGetPtr(Const ByRef $PTR)
	Local $_ptr=DllStructGetPtr($PTR)
	If @error Then $_ptr=$PTR
	Return $_ptr
EndFunc	;==>_SafeGetPtr
;=======================================================================
;	вспомогательные функции для тестового окна
;=======================================================================
Func _ESC_1()
	ProcessClose($iPID)
	Beep(1000,500)
	Do
		$err=FileDelete($nameArchv)
	Until $err
	Exit
EndFunc	;==>_ESC_1

Func _F11_1()
	If BitAnd(WinGetState($hGuiWin),16) Then
		GUISetState(@SW_RESTORE,$hGuiWin)
	Else
		GUISetState(@SW_MINIMIZE,$hGuiWin)
	EndIf
	Beep(1000,200)
EndFunc	;==> _F11_1()

Func _GetTabbedStringSizeEx($CtrlID,$sString)
	Local $tTM= DllStructCreate('long;long;long;long;long;long;long;long;long;long;long;wchar;wchar;wchar;wchar;byte;byte;byte;byte;byte')
	Local $pTM=DllStructGetPtr($tTM)
	Local $tData=DllStructCreate('long;long')
	Local $pData=DllStructGetPtr($tData)
	If Not IsHWnd($CtrlID) Then $CtrlID=GUICtrlGetHandle($CtrlID)
	Local $Ret=DllCall('user32.dll','ptr','GetDC','hwnd',$CtrlID)
	Local $hDC=$Ret[0]
	$Ret=DllCall('user32.dll','ptr','SendMessageW','hwnd',$CtrlID,'uint',0x0031,'wparam',0,'lparam',0)
	$Ret=DllCall('gdi32.dll','ptr','SelectObject','hwnd',$hDC,'ptr',$Ret[0])
	Local $hSv=$Ret[0]
	$Ret=DllCall('gdi32.dll','int','GetTextMetricsW','hwnd',$hDC,'ptr',$pTM)
	Local $Tab=8*DllStructGetData($tTM,6)
	DllStructSetData($tData,1,$Tab)
	$Ret=DllCall('user32.dll','dword','GetTabbedTextExtentW','hwnd',$hDC,'wstr',$sString,'int',StringLen($sString), _
		'int',1,'ptr',$pData)
	If $hSv Then DllCall('gdi32.dll','ptr','SelectObject','hwnd',$hDC,'ptr',$hSv)
	If $hDC Then DllCall('user32.dll','int','ReleaseDC','hwnd',$CtrlID,'hwnd',$hDC)
	Return BitAND($Ret[0],0xFFFF)
EndFunc	;==>_GetTabbedStringSizeEx

Все работает, но осталась одна нерешенная проблема. Мне нужно получать еще и код возврата от архиватора.
Можно ли это реализовать в данном случае?
Спасибо.
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
madmasles
madmasles сказал(а):
_WinAPI_GetExitCodeProcess()
Я не знаю как ее прикрутить здесь. Из своего опыта и найденных на форуме примеров, я знаю, что для работы этой функции нужно использовать $STDOUT_CHILD ($STDERR_MERGED) в функции RUN. Но при этом вывод в консоль прекращается и проценты уже не изменяются. Как получить и то и другое!? :stars:
 

Vini

Новичок
Сообщения
27
Репутация
0
Уважаемый gora, у меня почему-то не работает Ваш скрипт - консольном окне 7zip проценты идут, а в GUI показывает только объём файлов, а проценты постоянно на нуле. В чем может быть дело?
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
Vini
Не могу ответить, может дело в системе. У меня скрипт работает на win7 X64 и winXP X86. Решение в паблик не ушло и подтвердить его работоспособность у других не могу.
 
Автор
G

gora

Знающий
Сообщения
315
Репутация
19
gora [?]
Мне нужно получать еще и код возврата от архиватора.
Т.к., ответа так и не последовало пришлось решать задачу несколько другим способом, считывать и анализировать последнюю строку сообщения от архиватора. Может кому пригодится:
Код:
#include <APIConstants.au3>
#include <File.au3>
#include <StaticConstants.au3>

Dim $arrayCmdLin,$iPID,$sizeSelect,$widthWind

; файл список в кодировке WIN (1251). У меня он содержит одну строку (но может быть и несколько):
; x:\1
; в этой папке различные файлы и подпапки с файлами общим размером около 50 МБ
$fileList=@ScriptDir&"\List.txt"

; путь и имя выходного архива
$nameArchv="x:\"&@HOUR&"_"&@MIN&"_"&@SEC&"_test.7z"

; путь к архиватору
$p7z='C:\Program Files\7-Zip\'

; вспомогательные переменные для сжатия
$mtd='LZMA2'; метод сжатия
$dct=8; словарь в МБ 
$comline7z='-scsWIN -mmt2 -m0=BCJ2 -m1='&$mtd&':d'&$dct&'m -m2='&$mtd&':d21 -m3='&$mtd&':d21 -mb0:1 -mb0s1:2 -mb0s2:3'

;   расчет размера выделенных папок\файлов
_FileReadToArray($fileList,$arrayCmdLin)
For $i=1 To $arrayCmdLin[0]
	If StringInStr(FileGetAttrib($arrayCmdLin[$i]),'D') Then
		$sizeSelect+=DirGetSize($arrayCmdLin[$i])
	Else
		$sizeSelect+=FileGetSize($arrayCmdLin[$i])
	EndIf
Next
;************************************************************************************

$Title='Архивирование папок/файлов'
$Text='Размер выделенных папок/файлов|' _
	&StringRegExpReplace($sizeSelect,'(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))','\1 ')&@LF& _
	'Выбранный размер словаря (МБ)|'&$dct&@LF& _
	'Выбранный метод сжатия|'&$mtd&@LF& _
	'Имя архива|'&StringRegExpReplace($nameArchv,'^.*\\','')&@LF&@LF& _
	'Для прерывания архивирования нажмите клавишу ESC'&@LF& _
	'Свернуть/развернуть окно можно, нажав клавишу F11'
HotKeySet("{ESC}","_ESC_1")
HotKeySet('{F11}','_F11_1')
$hGuiWin=GUICreate('',0,0)
Opt('MouseCoordMode',2)
GUISetFont(8.5,800,0,'Tahoma')
GUICtrlCreateLabel('',0,0)
;   расчет размеров окна
$array=StringSplit($Text,@LF,2)
$heightWind=UBound($array)*16+20
For $i In $array
	$Width=_GetTabbedStringSizeEx(-1,$i)
	If $Width > $widthWind Then $widthWind=$Width
Next
$widthWind +=20
;   создание окна
$hGuiWin=GUICreate($Title,$widthWind+6,$heightWind+67,-1,-1,$WS_SYSMENU,-1)
GUISetFont(8.5,400,0,'Tahoma')
;   вывод текста
For $i=0 To UBound($array)-1
	$subline=StringSplit($array[$i],'|',1)
	If $i < UBound($array)-3 Then
		GUICtrlCreateLabel($subline[1],50,10+16*$i,_GetTabbedStringSizeEx(-1,$subline[1]),20)
		If $subline[0] > 1 Then
			$Width=_GetTabbedStringSizeEx(-1,$subline[2])
			GUICtrlCreateLabel($subline[2],$widthWind-$Width-10,10+16*$i,$Width,20,$SS_RIGHT)
		EndIf
	Else
		GUICtrlCreateLabel($subline[1],10,10+16*$i,_GetTabbedStringSizeEx(-1,$subline[1]),20)
		GUICtrlSetColor(-1,0xff0000)
		GUICtrlSetFont(-1,8.5,800)
	EndIf
Next
;   вывод иконки и звука
GUICtrlCreateIcon('user32.dll',4+100,10,10)
DllCall('user32.dll','int','MessageBeep','int',0x40)
;   прогрессбар и процент архивирования
$Progress=GUICtrlCreateProgress(10,$heightWind-5,$widthWind-20,20,1)
$Label=GUICtrlCreateLabel('0%',-1,$heightWind+20,$widthWind-20,20,1)
GUICtrlSetFont(-1,-1,800)
GUISetState(BitAND(@SW_DISABLE,@SW_SHOW),$hGuiWin)
;   запуск процесса архивирования
$errr = _7zRead('"'&$p7z&'7z.exe" a "'&$nameArchv&'" @"'&$fileList&'" '&$comline7z,$Progress,$Label)
If $errr <> '' Then MsgBox(1+256+48,'Ошибка 7-Zip',$errr)

GUIDelete($hGuiWin)
Exit
;=======================================================================

;main UDF ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;   Function:       _7zRead
;   Description:    Reads progress from 7zip window and sets control data
;   Parameters:     $sCmd = 7zip Commandline to be executed
;                   $iProgress = ControlID of Progress Control to be updated
;                   $iStatic = ControlID of a Static Control (label, button etc pp) to be updated
;                   $nShow = [optional] Flag for 7zip window, default is @SW_HIDE
;   Author:         jennico, basic script by valik

Func _7zRead($sCmd, $iProgress, $iStatic, $nShow=@SW_HIDE)
	$iPID=Run($sCmd,"",$nShow)
	ProcessWait($iPID)
	; Open the 7-Zip percent reader.
	Local $hPercent=Open7ZipPercent($iPID)
	Local $opercent=-1
	; Loop on the process existence.
	While ProcessExists($iPID)
		; Read the percent and update the progress bar.
		Local $nPercent=Read7ZipPercent($hPercent)
		If $nPercent >= 0 And $opercent <> $nPercent Then
			GUICtrlSetData($iProgress,$nPercent)
			GUICtrlSetData($iStatic,$nPercent&"%")
			$opercent=$nPercent
		Else
			Sleep(50)
		EndIf
	WEnd
	Local $OutLastLine = StringStripWS(_Read7Ziptxt($hPercent), 2)
	; Cleanup.
	If UBound($hPercent)=4 Then
		; Detach the console
		DllCall('Kernel32.dll','int',"FreeConsole")
		; Destroy the handle
		$hPercent=0
	EndIf
	If StringInStr($OutLastLine,'Everything is Ok') <> 1 Then Return $OutLastLine
	Return ''
EndFunc ;==>_7zRead

;internal helper functions ++++++++++++++++++++++++++++++++++++++++++++++++++++
Func Open7ZipPercent($pid)
	; Try to attach to the console of the PID.
	; Return 0 on failure.
	If _AttachConsole($pid)=0 Then Return 0
	; The user should treat this as an opaque handle, but internally it contains a handle and some structures.
	Local $vHandle[4]
	$vHandle[0]=_GetStdHandle(-11)  ; STDOUT Handle
	$vHandle[1]=DllStructCreate("short dwSizeX;short dwSizeY;short dwCursorPositionX;short dwCursorPositionY;short wAttributes;short Left;short Top;short Right;short Bottom;short dwMaximumWindowSizeX;short dwMaximumWindowSizeY")	; Screen Buffer structure
	$vHandle[2]=DllStructCreate("dword[4]") ; Data buffer
	$vHandle[3]=DllStructCreate("short Left;short Top;short Right;short Bottom")	; SMALL_RECT structure
	; Return the handle on success.
	Return $vHandle
EndFunc ;==>Open7ZipPercent
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Func _Read7Ziptxt(ByRef $vHandle, $Nline=-1)
	; Basic sanity check to validate the handle.
	Local $exit_txt=""
	If UBound($vHandle)=4 Then
		; Try to get the screen buffer information.
		If _GetConsoleScreenBufferInfo($vHandle[0],$vHandle[1]) Then
			For $s = 0 To 19
				; Load the SMALL_RECT with the projected text position.
				DllStructSetData($vHandle[3],"Left",$s*4)
				DllStructSetData($vHandle[3],"Top",DllStructGetData($vHandle[1],"dwCursorPositionY")+$Nline)
				DllStructSetData($vHandle[3],"Right",80)
				DllStructSetData($vHandle[3],"Bottom",DllStructGetData($vHandle[1],"dwCursorPositionY")+$Nline)
				; Read the console output.
				If _ReadConsoleOutput($vHandle[0],$vHandle[2],$vHandle[3]) Then
					; Читаем 4 символа
					For $i = 0 To 3
						Local $pCharInfo=DllStructCreate("wchar UnicodeChar;short Attributes", _
							DllStructGetPtr($vHandle[2])+($i*4))
						; Append the character.
						$exit_txt &=DllStructGetData($pCharInfo,"UnicodeChar")
					Next
				EndIf
			Next
		EndIf
	EndIf
	; On failure we return -1 which is obviously not a valid percentage.
	Return $exit_txt
EndFunc ;==>_Read7Ziptxt
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Func Read7ZipPercent(ByRef $vHandle)
	; Basic sanity check to validate the handle.
	If UBound($vHandle)=4 Then
		; Try to get the screen buffer information.
		If _GetConsoleScreenBufferInfo($vHandle[0],$vHandle[1]) Then
			; Load the SMALL_RECT with the projected text position.
			DllStructSetData($vHandle[3],"Left",DllStructGetData($vHandle[1],"dwCursorPositionX")-4)
			DllStructSetData($vHandle[3],"Top",DllStructGetData($vHandle[1],"dwCursorPositionY"))
			DllStructSetData($vHandle[3],"Right",DllStructGetData($vHandle[1],"dwCursorPositionX"))
			DllStructSetData($vHandle[3],"Bottom",DllStructGetData($vHandle[1],"dwCursorPositionY"))
			; Read the console output.
			If _ReadConsoleOutput($vHandle[0],$vHandle[2],$vHandle[3]) Then
				; This variable holds the output string.
				Local $sPercent=""
				; We iterate over 3 characters because that's all we read.
				For $i = 0 To 3
					Local $pCharInfo=DllStructCreate("wchar UnicodeChar;short Attributes", _
						DllStructGetPtr($vHandle[2])+($i*4))
					; Append the character.
					$sPercent &=DllStructGetData($pCharInfo,"UnicodeChar")
				Next
				; Ensure we read a valid percentage.  If so return the cast to a number.
				If StringRight($sPercent,1)="%" Then Return Number($sPercent,4)
			EndIf
		EndIf
	EndIf
	; On failure we return -1 which is obviously not a valid percentage.
	Return -1
EndFunc ;==>Read7ZipPercent
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Func _GetStdHandle($nHandle)
	Local $aRet=DllCall('Kernel32.dll','hwnd',"GetStdHandle",'dword',$nHandle)
	If @error Then Return SetError(@error,@extended,-1)
	Return $aRet[0]
EndFunc ;==>_GetStdHandle
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Func _AttachConsole($nPid)
	Local $aRet=DllCall('Kernel32.dll','int',"AttachConsole",'dword',$nPid)
	If @error Then Return SetError(@error,@extended,False)
	Return $aRet[0]
EndFunc ;==>_AttachConsole
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Func _GetConsoleScreenBufferInfo($hConsoleOutput,$pConsoleScreenBufferInfo)
	Local $aRet=DllCall('Kernel32.dll','int',"GetConsoleScreenBufferInfo",'hwnd',$hConsoleOutput,'ptr', _
		_SafeGetPtr($pConsoleScreenBufferInfo))
	If @error Then Return SetError(@error,@extended,False)
	Return $aRet[0]
EndFunc ;==>_GetConsoleScreenBufferInfo
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Func _ReadConsoleOutput($hConsoleOutput,$pBuffer,$pSmallRect);,65540,0,
	; We lie about the types for the COORD structures.  Since they are the size of an int we expect a packed
	; int.  Otherwise we may crash or just pass garbage.
	Local $aRet=DllCall('Kernel32.dll','int',"ReadConsoleOutputW",'ptr',$hConsoleOutput, _
		'ptr',_SafeGetPtr($pBuffer),'int',65540, 'int',0, _
		'ptr',_SafeGetPtr($pSmallRect))
	If @error Then SetError(@error,@extended,False)
	Return $aRet[0]
EndFunc ;==>_ReadConsoleOutput
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Func _SafeGetPtr(Const ByRef $PTR)
	Local $_ptr=DllStructGetPtr($PTR)
	If @error Then $_ptr=$PTR
	Return $_ptr
EndFunc ;==>_SafeGetPtr
;=======================================================================
;   вспомогательные функции для тестового окна
;=======================================================================
Func _ESC_1()
	ProcessClose($iPID)
	Beep(1000,500)
	Do
		$err=FileDelete($nameArchv)
	Until $err
	Exit
EndFunc ;==>_ESC_1

Func _F11_1()
	If BitAnd(WinGetState($hGuiWin),16) Then
		GUISetState(@SW_RESTORE,$hGuiWin)
	Else
		GUISetState(@SW_MINIMIZE,$hGuiWin)
	EndIf
	Beep(1000,200)
EndFunc ;==> _F11_1()

Func _GetTabbedStringSizeEx($CtrlID,$sString)
	Local $tTM= DllStructCreate('long;long;long;long;long;long;long;long;long;long;long;wchar;wchar;wchar;wchar;byte;byte;byte;byte;byte')
	Local $pTM=DllStructGetPtr($tTM)
	Local $tData=DllStructCreate('long;long')
	Local $pData=DllStructGetPtr($tData)
	If Not IsHWnd($CtrlID) Then $CtrlID=GUICtrlGetHandle($CtrlID)
	Local $Ret=DllCall('user32.dll','ptr','GetDC','hwnd',$CtrlID)
	Local $hDC=$Ret[0]
	$Ret=DllCall('user32.dll','ptr','SendMessageW','hwnd',$CtrlID,'uint',0x0031,'wparam',0,'lparam',0)
	$Ret=DllCall('gdi32.dll','ptr','SelectObject','hwnd',$hDC,'ptr',$Ret[0])
	Local $hSv=$Ret[0]
	$Ret=DllCall('gdi32.dll','int','GetTextMetricsW','hwnd',$hDC,'ptr',$pTM)
	Local $Tab=8*DllStructGetData($tTM,6)
	DllStructSetData($tData,1,$Tab)
	$Ret=DllCall('user32.dll','dword','GetTabbedTextExtentW','hwnd',$hDC,'wstr',$sString,'int',StringLen($sString), _
		'int',1,'ptr',$pData)
	If $hSv Then DllCall('gdi32.dll','ptr','SelectObject','hwnd',$hDC,'ptr',$hSv)
	If $hDC Then DllCall('user32.dll','int','ReleaseDC','hwnd',$CtrlID,'hwnd',$hDC)
	Return BitAND($Ret[0],0xFFFF)
EndFunc ;==>_GetTabbedStringSizeEx
 
Верх