jennico Posted March 15, 2009 Share Posted March 15, 2009 (edited) Lots of people have been looking for a way to read out and display the contents of the the 7zip cmd window.while there is no problem to read out the "7z t " and "7z l " commands by stdoutread, there is no easy way to get the text from the "7z a" (add to archive) command.finally i found a tricky solution written by valik (Screen_Scrape). at least it is able to read out the compression progress percentage. the script is deeply hidden in the chat forum. i was so glad about it that i built a little UDF around it. working perfectly.you can run the script as .au3 or #include it, but it cannot be run from SciTe.expandcollapse popup;Global UDF Constants +++++++++++++++++++++++++++++++++++++++++++++++++++++++ Global Const $STD_INPUT_HANDLE = -10 Global Const $STD_OUTPUT_HANDLE = -11 Global Const $STD_ERROR_HANDLE = -12 Global Const $INVALID_HANDLE_VALUE = -1 Global Const $_CONSOLE_SCREEN_BUFFER_INFO = "short dwSizeX; short dwSizeY;short dwCursorPositionX; short dwCursorPositionY; short wAttributes;short Left; short Top; short Right; short Bottom; short dwMaximumWindowSizeX; short dwMaximumWindowSizeY" Global Const $_COORD = "short X; short Y" Global Const $_CHAR_INFO = "wchar UnicodeChar; short Attributes" Global Const $_SMALL_RECT = "short Left; short Top; short Right; short Bottom" Global Const $K32 = "Kernel32.dll", $INT = "int", $HWN = "hwnd", $PTR = "ptr", $DWO = "dword" ;main UDF ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Function: _7zRead ; Description: Reads progress from 7zip window and sets control data ; Parameters: $sCmd = 7zip Commandline to be executed ; $iProgress = [optional] ControlID of Progress Control to be updated (if none, use "") ; $sProgress = [optional] 1 if Progress Bar Window has to be updated, "" if not ; $sProgressSubText = [optional] 1 if Progress Bar Subtext to be written, "" if not ; $iStatic = [optional] ControlID of a Static Control (label, button etc pp) to be updated (if none, use "") ; $iStaticText = [optional] Text for $iStatic, the percentage will be added ; $nShow = [optional] Flag for 7zip window, default is @SW_HIDE ; Author: jennico, basic script by valik Func _7zRead($sCmd, $iProgress="", $sProgress="", $sProgressSubText="", $iStatic="", $iStaticText="", $nShow = @SW_HIDE) $iPID = Run($sCmd, "", $nShow) ProcessWait($iPID) If $iStatic Then GUICtrlSetData($iStatic, $iStaticText & "0%") Local $hPercent = Open7ZipPercent($iPID), $opercent = -1 While ProcessExists($iPID) Local $nPercent = Read7ZipPercent($hPercent) If $nPercent >= 0 And $opercent <> $nPercent Then If $sProgressSubText Then $sProgressSubText = $nPercent If $sProgress Then ProgressSet($nPercent, $nPercent & "%") If $iProgress Then GUICtrlSetData($iProgress, $nPercent) If $iStatic Then GUICtrlSetData($iStatic, $iStaticText & $nPercent & "%") $opercent = $nPercent Else Sleep(50) EndIf WEnd Close7ZipPercent($hPercent) EndFunc ;==>_7zRead ;internal helper functions ++++++++++++++++++++++++++++++++++++++++++++++++++++ Func Open7ZipPercent($pid) If _AttachConsole($pid) = 0 Then Return Local $vHandle[4] $vHandle[0] = _GetStdHandle($STD_OUTPUT_HANDLE) $vHandle[1] = DllStructCreate($_CONSOLE_SCREEN_BUFFER_INFO) $vHandle[2] = DllStructCreate("dword[4]") $vHandle[3] = DllStructCreate($_SMALL_RECT) Return $vHandle EndFunc ;==>Open7ZipPercent Func Close7ZipPercent(ByRef $vHandle) If UBound($vHandle) <> 4 Then Return False DllCall($K32, $INT, "FreeConsole") $vHandle = 0 Return True EndFunc ;==>Close7ZipPercent Func Read7ZipPercent(ByRef $vHandle) If UBound($vHandle) = 4 Then Local Const $hStdOut = $vHandle[0] Local Const $pConsoleScreenBufferInfo = $vHandle[1] Local Const $pBuffer = $vHandle[2] Local Const $pSmallRect = $vHandle[3] If _GetConsoleScreenBufferInfo($hStdOut, $pConsoleScreenBufferInfo) Then DllStructSetData($pSmallRect, "Left", DllStructGetData($pConsoleScreenBufferInfo, "dwCursorPositionX") - 4) DllStructSetData($pSmallRect, "Top", DllStructGetData($pConsoleScreenBufferInfo, "dwCursorPositionY")) DllStructSetData($pSmallRect, "Right", DllStructGetData($pConsoleScreenBufferInfo, "dwCursorPositionX")) DllStructSetData($pSmallRect, "Bottom", DllStructGetData($pConsoleScreenBufferInfo, "dwCursorPositionY")) If _ReadConsoleOutput($hStdOut, $pBuffer, $pSmallRect) Then Local $sPercent = "" For $i = 0 To 3 Local $pCharInfo = DllStructCreate($_CHAR_INFO, DllStructGetPtr($pBuffer) + ($i * 4)) $sPercent &= DllStructGetData($pCharInfo, "UnicodeChar") Next If StringRight($sPercent, 1) = "%" Then Return Number($sPercent) EndIf EndIf EndIf Return -1 EndFunc ;==>Read7ZipPercent Func _GetStdHandle($nHandle) Local $aRet = DllCall($K32, $HWN, "GetStdHandle", $DWO, $nHandle) If @error Then Return SetError(@error, @extended, $INVALID_HANDLE_VALUE) Return $aRet[0] EndFunc ;==>_GetStdHandle Func _AttachConsole($nPid) Local $aRet = DllCall($K32, $INT, "AttachConsole", $DWO, $nPid) If @error Then Return SetError(@error, @extended, False) Return $aRet[0] EndFunc ;==>_AttachConsole Func _GetConsoleScreenBufferInfo($hConsoleOutput, $pConsoleScreenBufferInfo) Local $aRet = DllCall($K32, $INT, "GetConsoleScreenBufferInfo", $HWN, $hConsoleOutput, $PTR, _SafeGetPtr($pConsoleScreenBufferInfo)) If @error Then Return SetError(@error, @extended, False) Return $aRet[0] EndFunc ;==>_GetConsoleScreenBufferInfo Func _ReadConsoleOutput($hConsoleOutput, $pBuffer, $pSmallRect);, 65540, 0, Local $aRet = DllCall($K32, $INT, "ReadConsoleOutputW", $PTR, $hConsoleOutput, $INT, _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 ;example GUI +++++++++++++++++++++++++++++++++++++++++++++++++++++++ #include <WindowsConstants.au3> #include <EditConstants.au3> $gui = GUICreate("", 400, 189, Default, Default, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_TOPMOST) $Edit = GUICtrlCreateEdit("", 4, 4, 394, 156, BitOR($WS_VSCROLL, $ES_READONLY)) GUICtrlSetBkColor(-1, 0) GUICtrlSetColor(-1, 0xFFFFFF) GUICtrlSetFont(-1, 9, 800) $Progress = GUICtrlCreateProgress(4, 162, 394, 25, 1) GUICtrlSetColor(-1, 0xF200) $Label = GUICtrlCreateLabel("", 4, 167, 394, 20, 1) GUICtrlSetFont(-1, 9, 800) GUICtrlSetBkColor(-1, -2) GUISetState() HotKeySet("{ESC}", "_Exit") ProgressOn("7zipRead Example GUI", "Compressing", "", -1, @DesktopHeight / 2 - 200, 16) GUICtrlSetData($Edit, "Press <ESC> to abort", 1) $Folder = FileSelectFolder("Please Choose Directory to be Compressed" & @CRLF & "(Folder should contain several subs and some 100 MB)", @HomeDrive, 0, @HomeDrive, $gui) If StringRight($Folder, 2) = ":\" Then $Folder = StringTrimRight($Folder, 1) Dim $t, $search = FileFindFirstFile($Folder & "\*.*") Do $t &= FileFindNextFile($search) & "|" Until @error FileClose($search) $FileList = StringSplit(StringTrimRight($t, 2), "|") $Archiv = @HOUR & "_" & @MIN & "_" & @SEC & "_test.zip" For $i = 1 To $FileList[0] GUICtrlSetData($Edit, @CRLF & "...compressing " & $Folder & "\" & $FileList[$i] & " " & $i & " of " & $FileList[0] & " ...", 1) ProgressSet(0, "", "Compressing " & $Folder & "\" & $FileList[$i]) _7zRead("7z a -tzip " & $Archiv & " " & FileGetShortName($Folder & "\" & $FileList[$i]) & " -x!Thumbs.db", $Progress, 1, 1, $Label, $Folder & "\" & $FileList[$i] & " => ", @SW_SHOW) GUICtrlSetData($Edit, " OK", 1) Next ProgressSet(100,"100%") GUICtrlSetData($Progress,100) GUICtrlSetData($Label,$Folder&" => 100%") Dim $t="",$x = Run("7z l " & $Archiv & " -r", "", @SW_SHOW, 6) While @error = 0 $t &= StdoutRead($x) WEnd GUICtrlSetData($Edit,@CRLF&@CRLF&$t,1) While 1 Sleep(20) WEnd Func _Exit() ProcessClose("7z.exe") Exit EndFunc ;==>_Exitcheers j.Edit: updated example. it is better to pass FileGetShortName because of the spaces in file path. even better it would be to use @ComSpec with '' ...... i know ..... Edit2: inserted a sleep to avoid cpu load. Edited March 15, 2009 by jennico Spoiler I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.Don't forget this IP: 213.251.145.96 Link to comment Share on other sites More sharing options...
MrCreatoR Posted April 15, 2009 Share Posted April 15, 2009 (edited) Thanks, good UDF, definitly will use it Edited April 15, 2009 by MrCreatoR Spoiler Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1 AutoIt Russian Community My Work... Spoiler Projects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize ProgramUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF Examples: ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating ) * === My topics === * ================================================== ================================================== AutoIt is simple, subtle, elegant. © AutoIt Team Link to comment Share on other sites More sharing options...
135956 Posted September 16, 2009 Share Posted September 16, 2009 Thanks, good UDF. can use for makecab.exe? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now